mirror of
https://git.FreeBSD.org/src.git
synced 2026-06-02 11:24:32 +00:00
IPv6 support for lpr.
Reviewed by: freebsd-current (no objection) Obtained from: KAME
This commit is contained in:
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=70098
@@ -1,5 +1,6 @@
|
||||
# $FreeBSD$
|
||||
|
||||
CFLAGS+=-DINET6
|
||||
CWARNFLAGS= -Wall -Wnested-externs -Wmissing-prototypes -Wno-unused -Wredundant-decls -Wstrict-prototypes
|
||||
|
||||
.if exists(${.OBJDIR}/../common_source)
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
|
||||
#include <sys/queue.h>
|
||||
#include <time.h>
|
||||
#include <netdb.h>
|
||||
|
||||
/*
|
||||
* All this information used to be in global static variables shared
|
||||
@@ -156,14 +157,14 @@ extern char *name; /* program name */
|
||||
/* host machine name */
|
||||
extern char host[MAXHOSTNAMELEN];
|
||||
extern char *from; /* client's machine name */
|
||||
#define MAXIPSTRLEN 32 /* maxlen of an IP-address as a string */
|
||||
extern char from_ip[MAXIPSTRLEN]; /* client machine's IP address */
|
||||
extern char from_ip[NI_MAXHOST]; /* client machine's IP address */
|
||||
|
||||
extern int requ[]; /* job number of spool entries */
|
||||
extern int requests; /* # of spool requests */
|
||||
extern char *user[]; /* users to process */
|
||||
extern int users; /* # of users in user array */
|
||||
extern char *person; /* name of person doing lprm */
|
||||
extern u_char family; /* address family */
|
||||
|
||||
/*
|
||||
* Structure used for building a sorted list of control files.
|
||||
|
||||
@@ -67,7 +67,13 @@ static const char rcsid[] =
|
||||
|
||||
char host[MAXHOSTNAMELEN]; /* host machine name */
|
||||
char *from = host; /* client's machine name */
|
||||
char from_ip[MAXIPSTRLEN] = ""; /* client machine's IP address */
|
||||
char from_ip[NI_MAXHOST] = ""; /* client machine's IP address */
|
||||
|
||||
#ifdef INET6
|
||||
u_char family = PF_UNSPEC;
|
||||
#else
|
||||
u_char family = PF_INET;
|
||||
#endif
|
||||
|
||||
extern uid_t uid, euid;
|
||||
|
||||
@@ -79,46 +85,52 @@ extern uid_t uid, euid;
|
||||
int
|
||||
getport(const struct printer *pp, const char *rhost, int rport)
|
||||
{
|
||||
struct hostent *hp;
|
||||
struct servent *sp;
|
||||
struct sockaddr_in sin;
|
||||
struct addrinfo hints, *res, *ai;
|
||||
int s, timo = 1, lport = IPPORT_RESERVED - 1;
|
||||
int err;
|
||||
int err, refused = 0;
|
||||
|
||||
/*
|
||||
* Get the host address and port number to connect to.
|
||||
*/
|
||||
if (rhost == NULL)
|
||||
fatal(pp, "no remote host to connect to");
|
||||
bzero((char *)&sin, sizeof(sin));
|
||||
sin.sin_len = sizeof sin;
|
||||
sin.sin_family = AF_INET;
|
||||
if (inet_aton(rhost, &sin.sin_addr) == 0) {
|
||||
hp = gethostbyname2(rhost, AF_INET);
|
||||
if (hp == NULL)
|
||||
fatal(pp, "cannot resolve %s: %s", rhost,
|
||||
hstrerror(h_errno));
|
||||
/* XXX - should deal with more addresses */
|
||||
sin.sin_addr = *(struct in_addr *)hp->h_addr_list[0];
|
||||
}
|
||||
if (rport == 0) {
|
||||
sp = getservbyname("printer", "tcp");
|
||||
if (sp == NULL)
|
||||
fatal(pp, "printer/tcp: unknown service");
|
||||
sin.sin_port = sp->s_port;
|
||||
} else
|
||||
sin.sin_port = htons(rport);
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = family;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_protocol = 0;
|
||||
err = getaddrinfo(rhost, (rport == 0 ? "printer" : NULL),
|
||||
&hints, &res);
|
||||
if (err)
|
||||
fatal(pp, "%s\n", gai_strerror(err));
|
||||
if (rport != 0)
|
||||
((struct sockaddr_in *) res->ai_addr)->sin_port = htons(rport);
|
||||
|
||||
/*
|
||||
* Try connecting to the server.
|
||||
*/
|
||||
ai = res;
|
||||
retry:
|
||||
seteuid(euid);
|
||||
s = rresvport(&lport);
|
||||
s = rresvport_af(&lport, ai->ai_family);
|
||||
seteuid(uid);
|
||||
if (s < 0)
|
||||
if (s < 0) {
|
||||
if (errno != EAGAIN) {
|
||||
if (ai->ai_next) {
|
||||
ai = ai->ai_next;
|
||||
goto retry;
|
||||
}
|
||||
if (refused && timo <= 16) {
|
||||
sleep(timo);
|
||||
timo *= 2;
|
||||
refused = 0;
|
||||
ai = res;
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
freeaddrinfo(res);
|
||||
return(-1);
|
||||
if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
|
||||
}
|
||||
if (connect(s, ai->ai_addr, ai->ai_addrlen) < 0) {
|
||||
err = errno;
|
||||
(void) close(s);
|
||||
errno = err;
|
||||
@@ -128,16 +140,28 @@ retry:
|
||||
* rresvport should guarantee that the chosen port will
|
||||
* never result in an EADDRINUSE).
|
||||
*/
|
||||
if (errno == EADDRINUSE)
|
||||
goto retry;
|
||||
|
||||
if (errno == ECONNREFUSED && timo <= 16) {
|
||||
sleep(timo);
|
||||
timo *= 2;
|
||||
if (errno == EADDRINUSE) {
|
||||
goto retry;
|
||||
}
|
||||
|
||||
if (errno == ECONNREFUSED)
|
||||
refused++;
|
||||
|
||||
if (ai->ai_next != NULL) {
|
||||
ai = ai->ai_next;
|
||||
goto retry;
|
||||
}
|
||||
if (refused && timo <= 16) {
|
||||
sleep(timo);
|
||||
timo *= 2;
|
||||
refused = 0;
|
||||
ai = res;
|
||||
goto retry;
|
||||
}
|
||||
freeaddrinfo(res);
|
||||
return(-1);
|
||||
}
|
||||
freeaddrinfo(res);
|
||||
return(s);
|
||||
}
|
||||
|
||||
@@ -155,10 +179,10 @@ char *
|
||||
checkremote(struct printer *pp)
|
||||
{
|
||||
char name[MAXHOSTNAMELEN];
|
||||
register struct hostent *hp;
|
||||
struct addrinfo hints, *local_res, *remote_res, *lr, *rr;
|
||||
char *err;
|
||||
struct in_addr *localaddrs;
|
||||
int i, j, nlocaladdrs, ncommonaddrs;
|
||||
int ncommonaddrs, error;
|
||||
char h1[NI_MAXHOST], h2[NI_MAXHOST];
|
||||
|
||||
if (!pp->rp_matches_local) { /* Remote printer doesn't match local */
|
||||
pp->remote = 1;
|
||||
@@ -166,57 +190,63 @@ checkremote(struct printer *pp)
|
||||
}
|
||||
|
||||
pp->remote = 0; /* assume printer is local */
|
||||
if (pp->remote_host != NULL) {
|
||||
/* get the addresses of the local host */
|
||||
gethostname(name, sizeof(name));
|
||||
name[sizeof(name) - 1] = '\0';
|
||||
hp = gethostbyname2(name, AF_INET);
|
||||
if (hp == (struct hostent *) NULL) {
|
||||
asprintf(&err, "unable to get official name "
|
||||
"for local machine %s: %s",
|
||||
name, hstrerror(h_errno));
|
||||
return err;
|
||||
}
|
||||
for (i = 0; hp->h_addr_list[i]; i++)
|
||||
;
|
||||
nlocaladdrs = i;
|
||||
localaddrs = malloc(i * sizeof(struct in_addr));
|
||||
if (localaddrs == 0) {
|
||||
asprintf(&err, "malloc %lu bytes failed",
|
||||
(u_long)i * sizeof(struct in_addr));
|
||||
return err;
|
||||
}
|
||||
for (i = 0; hp->h_addr_list[i]; i++)
|
||||
localaddrs[i] = *(struct in_addr *)hp->h_addr_list[i];
|
||||
if (pp->remote_host == NULL)
|
||||
return NULL;
|
||||
|
||||
/* get the official name of RM */
|
||||
hp = gethostbyname2(pp->remote_host, AF_INET);
|
||||
if (hp == (struct hostent *) NULL) {
|
||||
asprintf(&err, "unable to get address list for "
|
||||
"remote machine %s: %s",
|
||||
pp->remote_host, hstrerror(h_errno));
|
||||
free(localaddrs);
|
||||
return err;
|
||||
}
|
||||
/* get the addresses of the local host */
|
||||
gethostname(name, sizeof(name));
|
||||
name[sizeof(name) - 1] = '\0';
|
||||
|
||||
ncommonaddrs = 0;
|
||||
for (i = 0; i < nlocaladdrs; i++) {
|
||||
for (j = 0; hp->h_addr_list[j]; j++) {
|
||||
char *them = hp->h_addr_list[j];
|
||||
if (localaddrs[i].s_addr ==
|
||||
(*(struct in_addr *)them).s_addr)
|
||||
ncommonaddrs++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* if the two hosts do not share at least one IP address
|
||||
* then the printer must be remote.
|
||||
*/
|
||||
if (ncommonaddrs == 0)
|
||||
pp->remote = 1;
|
||||
free(localaddrs);
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = family;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
if ((error = getaddrinfo(name, NULL, &hints, &local_res)) != 0) {
|
||||
asprintf(&err, "unable to get official name "
|
||||
"for local machine %s: %s",
|
||||
name, gai_strerror(error));
|
||||
return err;
|
||||
}
|
||||
|
||||
/* get the official name of RM */
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = family;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
if ((error = getaddrinfo(pp->remote_host, NULL,
|
||||
&hints, &remote_res)) != 0) {
|
||||
asprintf(&err, "unable to get address list for "
|
||||
"remote machine %s: %s",
|
||||
pp->remote_host, gai_strerror(error));
|
||||
freeaddrinfo(local_res);
|
||||
return err;
|
||||
}
|
||||
|
||||
ncommonaddrs = 0;
|
||||
for (lr = local_res; lr; lr = lr->ai_next) {
|
||||
h1[0] = '\0';
|
||||
if (getnameinfo(lr->ai_addr, lr->ai_addrlen, h1, sizeof(h1),
|
||||
NULL, 0, NI_NUMERICHOST | NI_WITHSCOPEID) != 0)
|
||||
continue;
|
||||
for (rr = remote_res; rr; rr = rr->ai_next) {
|
||||
h2[0] = '\0';
|
||||
if (getnameinfo(rr->ai_addr, rr->ai_addrlen,
|
||||
h2, sizeof(h2), NULL, 0,
|
||||
NI_NUMERICHOST | NI_WITHSCOPEID) != 0)
|
||||
continue;
|
||||
if (strcmp(h1, h2) == 0)
|
||||
ncommonaddrs++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* if the two hosts do not share at least one IP address
|
||||
* then the printer must be remote.
|
||||
*/
|
||||
if (ncommonaddrs == 0)
|
||||
pp->remote = 1;
|
||||
freeaddrinfo(local_res);
|
||||
freeaddrinfo(remote_res);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
.Nd line printer spooler daemon
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl dlp
|
||||
.Op Fl dlp46
|
||||
.Op Ar port#
|
||||
.Sh DESCRIPTION
|
||||
.Nm Lpd
|
||||
@@ -81,6 +81,12 @@ The
|
||||
flag causes
|
||||
.Nm
|
||||
not to open an Internet listening socket.
|
||||
.It Fl 4
|
||||
Inet only.
|
||||
.It Fl 6
|
||||
Inet6 only.
|
||||
.It Fl 46
|
||||
Inet and inet6 (default).
|
||||
.It Ar "port#"
|
||||
The Internet port number used to rendezvous
|
||||
with other processes is normally obtained with
|
||||
|
||||
+184
-61
@@ -112,12 +112,14 @@ static void reapchild __P((int));
|
||||
static void mcleanup __P((int));
|
||||
static void doit __P((void));
|
||||
static void startup __P((void));
|
||||
static void chkhost __P((struct sockaddr_in *));
|
||||
static void chkhost __P((struct sockaddr *));
|
||||
static int ckqueue __P((struct printer *));
|
||||
static void usage __P((void));
|
||||
/* From rcmd.c: */
|
||||
int __ivaliduser __P((FILE *, u_long, const char *,
|
||||
const char *));
|
||||
static int *socksetup __P((int, int));
|
||||
|
||||
/* XXX from libc/net/rcmd.c */
|
||||
extern int __ivaliduser_sa __P((FILE *, struct sockaddr *, socklen_t,
|
||||
const char *, const char *));
|
||||
|
||||
uid_t uid, euid;
|
||||
|
||||
@@ -126,13 +128,14 @@ main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
int errs, f, funix, finet, fromlen, i, socket_debug;
|
||||
int errs, f, funix, *finet, fromlen, i, options, socket_debug;
|
||||
fd_set defreadfds;
|
||||
struct sockaddr_un un, fromunix;
|
||||
struct sockaddr_in sin, frominet;
|
||||
struct sockaddr_storage frominet;
|
||||
int lfd;
|
||||
sigset_t omask, nmask;
|
||||
struct servent *sp, serv;
|
||||
int inet_flag = 0, inet6_flag = 0;
|
||||
|
||||
euid = geteuid(); /* these shouldn't be different */
|
||||
uid = getuid();
|
||||
@@ -145,7 +148,7 @@ main(argc, argv)
|
||||
errx(EX_NOPERM,"must run as root");
|
||||
|
||||
errs = 0;
|
||||
while ((i = getopt(argc, argv, "dlp")) != -1)
|
||||
while ((i = getopt(argc, argv, "dlp46")) != -1)
|
||||
switch (i) {
|
||||
case 'd':
|
||||
socket_debug++;
|
||||
@@ -156,9 +159,19 @@ main(argc, argv)
|
||||
case 'p':
|
||||
pflag++;
|
||||
break;
|
||||
case '4':
|
||||
family = PF_INET;
|
||||
inet_flag++;
|
||||
break;
|
||||
case '6':
|
||||
family = PF_INET6;
|
||||
inet6_flag++;
|
||||
break;
|
||||
default:
|
||||
errs++;
|
||||
}
|
||||
if (inet_flag && inet6_flag)
|
||||
family = PF_UNSPEC;
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
if (errs)
|
||||
@@ -283,32 +296,17 @@ main(argc, argv)
|
||||
FD_ZERO(&defreadfds);
|
||||
FD_SET(funix, &defreadfds);
|
||||
listen(funix, 5);
|
||||
finet = -1;
|
||||
if (pflag == 0) {
|
||||
finet = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (finet >= 0) {
|
||||
i = 1;
|
||||
if (setsockopt(finet, SOL_SOCKET, SO_REUSEADDR, &i,
|
||||
sizeof i) < 0) {
|
||||
syslog(LOG_ERR, "setsockopt(SO_REUSEADDR): %m");
|
||||
mcleanup(0);
|
||||
}
|
||||
if (socket_debug &&
|
||||
setsockopt(finet, SOL_SOCKET, SO_DEBUG,
|
||||
&socket_debug, sizeof(socket_debug)) < 0) {
|
||||
syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m");
|
||||
mcleanup(0);
|
||||
}
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_port = sp->s_port;
|
||||
if (bind(finet, (struct sockaddr *)&sin,
|
||||
sizeof(sin)) < 0) {
|
||||
syslog(LOG_ERR, "bind: %m");
|
||||
mcleanup(0);
|
||||
}
|
||||
FD_SET(finet, &defreadfds);
|
||||
listen(finet, 5);
|
||||
options = SO_REUSEADDR;
|
||||
if (socket_debug)
|
||||
options |= SO_DEBUG;
|
||||
finet = socksetup(family, options);
|
||||
} else
|
||||
finet = NULL; /* pretend we couldn't open TCP socket. */
|
||||
if (finet) {
|
||||
for (i = 1; i <= *finet; i++) {
|
||||
FD_SET(finet[i], &defreadfds);
|
||||
listen(finet[i], 5);
|
||||
}
|
||||
}
|
||||
/*
|
||||
@@ -322,7 +320,7 @@ main(argc, argv)
|
||||
* XXX - should be redone for multi-protocol
|
||||
*/
|
||||
for (;;) {
|
||||
int domain, nfds, s;
|
||||
int domain = -1, nfds, s = -1;
|
||||
fd_set readfds;
|
||||
|
||||
FD_COPY(&defreadfds, &readfds);
|
||||
@@ -338,14 +336,15 @@ main(argc, argv)
|
||||
domain = AF_UNIX, fromlen = sizeof(fromunix);
|
||||
s = accept(funix,
|
||||
(struct sockaddr *)&fromunix, &fromlen);
|
||||
} else if (pflag == 0) /* if (FD_ISSET(finet, &readfds)) */ {
|
||||
domain = AF_INET, fromlen = sizeof(frominet);
|
||||
s = accept(finet,
|
||||
(struct sockaddr *)&frominet, &fromlen);
|
||||
if (frominet.sin_port == htons(20)) {
|
||||
close(s);
|
||||
continue;
|
||||
}
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
if (s < 0) {
|
||||
if (errno != EINTR)
|
||||
@@ -359,14 +358,16 @@ main(argc, argv)
|
||||
signal(SIGQUIT, SIG_IGN);
|
||||
signal(SIGTERM, SIG_IGN);
|
||||
(void) close(funix);
|
||||
if (pflag == 0) {
|
||||
(void) close(finet);
|
||||
if (pflag == 0 && finet) {
|
||||
for (i = 1; i <= *finet; i++)
|
||||
(void)close(finet[i]);
|
||||
}
|
||||
dup2(s, 1);
|
||||
(void) close(s);
|
||||
if (domain == AF_INET) {
|
||||
/* for both AF_INET and AF_INET6 */
|
||||
from_remote = 1;
|
||||
chkhost(&frominet);
|
||||
chkhost((struct sockaddr *)&frominet);
|
||||
} else
|
||||
from_remote = 0;
|
||||
doit();
|
||||
@@ -606,35 +607,75 @@ ckqueue(pp)
|
||||
*/
|
||||
static void
|
||||
chkhost(f)
|
||||
struct sockaddr_in *f;
|
||||
struct sockaddr *f;
|
||||
{
|
||||
register struct hostent *hp;
|
||||
struct addrinfo hints, *res, *r;
|
||||
register FILE *hostf;
|
||||
int first = 1;
|
||||
int good = 0;
|
||||
char host[NI_MAXHOST], ip[NI_MAXHOST];
|
||||
char serv[NI_MAXSERV];
|
||||
int error, addrlen;
|
||||
caddr_t addr;
|
||||
|
||||
error = getnameinfo(f, f->sa_len, NULL, 0, serv, sizeof(serv),
|
||||
NI_NUMERICSERV);
|
||||
if (error || atoi(serv) >= IPPORT_RESERVED)
|
||||
fatal(0, "Malformed from address");
|
||||
|
||||
/* Need real hostname for temporary filenames */
|
||||
hp = gethostbyaddr((char *)&f->sin_addr,
|
||||
sizeof(struct in_addr), f->sin_family);
|
||||
if (hp == NULL)
|
||||
fatal(0, "Host name for your address (%s) unknown",
|
||||
inet_ntoa(f->sin_addr));
|
||||
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 | NI_WITHSCOPEID);
|
||||
if (error)
|
||||
fatal(0, "Host name for your address unknown");
|
||||
else
|
||||
fatal(0, "Host name for your address (%s) unknown",
|
||||
host);
|
||||
}
|
||||
|
||||
(void) strncpy(fromb, hp->h_name, sizeof(fromb) - 1);
|
||||
(void)strncpy(fromb, host, sizeof(fromb) - 1);
|
||||
fromb[sizeof(fromb) - 1] = '\0';
|
||||
from = fromb;
|
||||
strncpy(from_ip, inet_ntoa(f->sin_addr), MAXIPSTRLEN);
|
||||
|
||||
/* Need address in stringform for comparison (no DNS lookup here) */
|
||||
error = getnameinfo(f, f->sa_len, host, sizeof(host), NULL, 0,
|
||||
NI_NUMERICHOST | NI_WITHSCOPEID);
|
||||
if (error)
|
||||
fatal(0, "Cannot print address");
|
||||
strncpy(from_ip, host, NI_MAXHOST);
|
||||
from_ip[sizeof(from_ip) - 1] = '\0';
|
||||
|
||||
/* Reject numeric addresses */
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = family;
|
||||
hints.ai_socktype = SOCK_DGRAM; /*dummy*/
|
||||
hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
|
||||
if (getaddrinfo(fromb, NULL, &hints, &res) == 0) {
|
||||
freeaddrinfo(res);
|
||||
fatal(0, "reverse lookup results in non-FQDN %s", fromb);
|
||||
}
|
||||
|
||||
/* Check for spoof, ala rlogind */
|
||||
hp = gethostbyname(fromb);
|
||||
if (!hp)
|
||||
fatal(0, "hostname for your address (%s) unknown", from_ip);
|
||||
for (; good == 0 && hp->h_addr_list[0] != NULL; hp->h_addr_list++) {
|
||||
if (!bcmp(hp->h_addr_list[0], (caddr_t)&f->sin_addr,
|
||||
sizeof(f->sin_addr)))
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = family;
|
||||
hints.ai_socktype = SOCK_DGRAM; /*dummy*/
|
||||
error = getaddrinfo(fromb, NULL, &hints, &res);
|
||||
if (error) {
|
||||
fatal(0, "hostname for your address (%s) unknown: %s", from_ip,
|
||||
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 | NI_WITHSCOPEID);
|
||||
if (!error && !strcmp(from_ip, ip))
|
||||
good = 1;
|
||||
}
|
||||
if (res)
|
||||
freeaddrinfo(res);
|
||||
if (good == 0)
|
||||
fatal(0, "address for your hostname (%s) not matched",
|
||||
from_ip);
|
||||
@@ -642,8 +683,7 @@ chkhost(f)
|
||||
hostf = fopen(_PATH_HOSTSEQUIV, "r");
|
||||
again:
|
||||
if (hostf) {
|
||||
if (__ivaliduser(hostf, f->sin_addr.s_addr,
|
||||
DUMMY, DUMMY) == 0) {
|
||||
if (__ivaliduser_sa(hostf, f, f->sa_len, DUMMY, DUMMY) == 0) {
|
||||
(void) fclose(hostf);
|
||||
return;
|
||||
}
|
||||
@@ -664,3 +704,86 @@ usage()
|
||||
fprintf(stderr, "usage: lpd [-dlp] [port#]\n");
|
||||
exit(EX_USAGE);
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
static int *
|
||||
socksetup(af, options)
|
||||
int af, options;
|
||||
{
|
||||
struct addrinfo hints, *res, *r;
|
||||
int error, maxs, *s, *socks;
|
||||
const int on = 1;
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
hints.ai_family = af;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
error = getaddrinfo(NULL, "printer", &hints, &res);
|
||||
if (error) {
|
||||
syslog(LOG_ERR, "%s", gai_strerror(error));
|
||||
mcleanup(0);
|
||||
}
|
||||
|
||||
/* Count max number of sockets we may open */
|
||||
for (maxs = 0, r = res; r; r = r->ai_next, maxs++)
|
||||
;
|
||||
socks = malloc((maxs + 1) * sizeof(int));
|
||||
if (!socks) {
|
||||
syslog(LOG_ERR, "couldn't allocate memory for sockets");
|
||||
mcleanup(0);
|
||||
}
|
||||
|
||||
*socks = 0; /* num of sockets counter at start of array */
|
||||
s = socks + 1;
|
||||
for (r = res; r; r = r->ai_next) {
|
||||
*s = socket(r->ai_family, r->ai_socktype, r->ai_protocol);
|
||||
if (*s < 0) {
|
||||
syslog(LOG_DEBUG, "socket(): %m");
|
||||
continue;
|
||||
}
|
||||
if (options & SO_REUSEADDR)
|
||||
if (setsockopt(*s, SOL_SOCKET, SO_REUSEADDR, &on,
|
||||
sizeof(on)) < 0) {
|
||||
syslog(LOG_ERR, "setsockopt(SO_REUSEADDR): %m");
|
||||
close(*s);
|
||||
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;
|
||||
}
|
||||
#ifdef IPV6_BINDV6ONLY
|
||||
if (r->ai_family == AF_INET6) {
|
||||
if (setsockopt(*s, IPPROTO_IPV6, IPV6_BINDV6ONLY,
|
||||
&on, sizeof(on)) < 0) {
|
||||
syslog(LOG_ERR,
|
||||
"setsockopt (IPV6_BINDV6ONLY): %m");
|
||||
close(*s);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (bind(*s, r->ai_addr, r->ai_addrlen) < 0) {
|
||||
syslog(LOG_DEBUG, "bind(): %m");
|
||||
close(*s);
|
||||
continue;
|
||||
}
|
||||
(*socks)++;
|
||||
s++;
|
||||
}
|
||||
|
||||
if (res)
|
||||
freeaddrinfo(res);
|
||||
|
||||
if (*socks == 0) {
|
||||
syslog(LOG_ERR, "Couldn't bind to any socket");
|
||||
free(socks);
|
||||
mcleanup(0);
|
||||
}
|
||||
return(socks);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user