IPv6 support, using rcmd-family funciton added.
NetBSD PR: 9050 From: Feico Dillema
This commit is contained in:
parent
5b1aaa939e
commit
33ba3a0f18
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: common.c,v 1.16 1999/12/05 22:10:57 jdolecek Exp $ */
|
||||
/* $NetBSD: common.c,v 1.17 2000/01/27 05:39:50 itojun Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1983, 1993
|
||||
@ -43,7 +43,7 @@
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)common.c 8.5 (Berkeley) 4/28/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: common.c,v 1.16 1999/12/05 22:10:57 jdolecek Exp $");
|
||||
__RCSID("$NetBSD: common.c,v 1.17 2000/01/27 05:39:50 itojun Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
@ -128,60 +128,54 @@ getport(rhost, rport)
|
||||
char *rhost;
|
||||
int rport;
|
||||
{
|
||||
struct hostent *hp;
|
||||
struct servent *sp;
|
||||
struct sockaddr_in sin;
|
||||
struct addrinfo hints, *res, *r;
|
||||
u_int timo = 1;
|
||||
int s, lport = IPPORT_RESERVED - 1;
|
||||
int err;
|
||||
int error;
|
||||
|
||||
/*
|
||||
* Get the host address and port number to connect to.
|
||||
*/
|
||||
if (rhost == NULL)
|
||||
fatal("no remote host to connect to");
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
if (inet_aton(rhost, &sin.sin_addr) == 1)
|
||||
sin.sin_family = AF_INET;
|
||||
else {
|
||||
hp = gethostbyname(rhost);
|
||||
if (hp == NULL)
|
||||
fatal("unknown host %s", rhost);
|
||||
memmove(&sin.sin_addr, hp->h_addr, (size_t)hp->h_length);
|
||||
sin.sin_family = hp->h_addrtype;
|
||||
}
|
||||
if (rport == 0) {
|
||||
sp = getservbyname("printer", "tcp");
|
||||
if (sp == NULL)
|
||||
fatal("printer/tcp: unknown service");
|
||||
sin.sin_port = sp->s_port;
|
||||
} else
|
||||
sin.sin_port = htons(rport);
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = PF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
error = getaddrinfo(rhost, "printer", &hints, &res);
|
||||
if (error)
|
||||
fatal("printer/tcp: %s", gai_strerror(error));
|
||||
|
||||
/*
|
||||
* Try connecting to the server.
|
||||
*/
|
||||
s = -1;
|
||||
for (r = res; r; r = r->ai_next) {
|
||||
retry:
|
||||
seteuid(euid);
|
||||
s = rresvport(&lport);
|
||||
seteuid(uid);
|
||||
if (s < 0)
|
||||
return(-1);
|
||||
if (connect(s, (const struct sockaddr *)&sin, sizeof(sin)) < 0) {
|
||||
err = errno;
|
||||
(void)close(s);
|
||||
errno = err;
|
||||
if (errno == EADDRINUSE) {
|
||||
lport--;
|
||||
goto retry;
|
||||
}
|
||||
if (errno == ECONNREFUSED && timo <= 16) {
|
||||
sleep(timo);
|
||||
timo *= 2;
|
||||
goto retry;
|
||||
}
|
||||
return(-1);
|
||||
seteuid(euid);
|
||||
s = rresvport_af(&lport, r->ai_family);
|
||||
seteuid(uid);
|
||||
if (s < 0)
|
||||
return(-1);
|
||||
if (connect(s, r->ai_addr, r->ai_addrlen) < 0) {
|
||||
error = errno;
|
||||
(void)close(s);
|
||||
s = -1;
|
||||
errno = error;
|
||||
if (errno == EADDRINUSE) {
|
||||
lport--;
|
||||
goto retry;
|
||||
}
|
||||
if (errno == ECONNREFUSED && timo <= 16) {
|
||||
sleep(timo);
|
||||
timo *= 2;
|
||||
goto retry;
|
||||
}
|
||||
continue;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
if (res)
|
||||
freeaddrinfo(res);
|
||||
return(s);
|
||||
}
|
||||
|
||||
@ -299,45 +293,63 @@ compar(p1, p2)
|
||||
/*
|
||||
* Figure out whether the local machine is the same
|
||||
* as the remote machine (RM) entry (if it exists).
|
||||
*
|
||||
* XXX not really the right way to determine.
|
||||
*/
|
||||
char *
|
||||
checkremote()
|
||||
{
|
||||
char hname[MAXHOSTNAMELEN + 1];
|
||||
struct hostent *hp;
|
||||
char hname[NI_MAXHOST];
|
||||
struct addrinfo hints, *res;
|
||||
static char errbuf[128];
|
||||
int error;
|
||||
|
||||
remote = 0; /* assume printer is local */
|
||||
if (RM != NULL) {
|
||||
/* get the official name of the local host */
|
||||
gethostname(hname, sizeof(hname));
|
||||
hname[sizeof(hname)-1] = '\0';
|
||||
hp = gethostbyname(hname);
|
||||
if (hp == (struct hostent *) NULL) {
|
||||
(void)snprintf(errbuf, sizeof(errbuf),
|
||||
"unable to get official name for local machine %s",
|
||||
hname);
|
||||
return errbuf;
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_flags = AI_CANONNAME;
|
||||
hints.ai_family = PF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
res = NULL;
|
||||
error = getaddrinfo(hname, NULL, &hints, &res);
|
||||
if (error) {
|
||||
(void)snprintf(errbuf, sizeof(errbuf),
|
||||
"unable to get official name for local machine %s: "
|
||||
"%s", hname, gai_strerror(error));
|
||||
return errbuf;
|
||||
} else {
|
||||
(void)strncpy(hname, hp->h_name, sizeof(hname) - 1);
|
||||
(void)strncpy(hname, res->ai_canonname,
|
||||
sizeof(hname) - 1);
|
||||
hname[sizeof(hname) - 1] = '\0';
|
||||
}
|
||||
freeaddrinfo(res);
|
||||
|
||||
/* get the official name of RM */
|
||||
hp = gethostbyname(RM);
|
||||
if (hp == (struct hostent *) NULL) {
|
||||
(void)snprintf(errbuf, sizeof(errbuf),
|
||||
"unable to get official name for remote machine %s",
|
||||
RM);
|
||||
return errbuf;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_flags = AI_CANONNAME;
|
||||
hints.ai_family = PF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
res = NULL;
|
||||
error = getaddrinfo(RM, NULL, &hints, &res);
|
||||
if (error) {
|
||||
(void)snprintf(errbuf, sizeof(errbuf),
|
||||
"unable to get official name for local machine %s: "
|
||||
"%s", RM, gai_strerror(error));
|
||||
return errbuf;
|
||||
}
|
||||
|
||||
/*
|
||||
* if the two hosts are not the same,
|
||||
* then the printer must be remote.
|
||||
*/
|
||||
if (strcasecmp(hname, hp->h_name) != 0)
|
||||
if (strcasecmp(hname, res->ai_canonname) != 0)
|
||||
remote = 1;
|
||||
|
||||
freeaddrinfo(res);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: extern.h,v 1.7 1997/10/05 15:12:12 mrg Exp $ */
|
||||
/* $NetBSD: extern.h,v 1.8 2000/01/27 05:39:50 itojun Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
@ -64,4 +64,6 @@ void sttyclearlflags __P((struct termios *tp, int flags));
|
||||
void sttysetlflags __P((struct termios *tp, int flags));
|
||||
|
||||
/* XXX from libc/net/rcmd.c */
|
||||
int __ivaliduser __P((FILE *, u_int32_t, const char *, const char *));
|
||||
struct sockaddr;
|
||||
int __ivaliduser_sa __P((FILE *, struct sockaddr *, const char *,
|
||||
const char *));
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: lpd.c,v 1.19 1999/12/23 02:10:07 mjl Exp $ */
|
||||
/* $NetBSD: lpd.c,v 1.20 2000/01/27 05:39:50 itojun Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1983, 1993, 1994
|
||||
@ -45,7 +45,7 @@ __COPYRIGHT("@(#) Copyright (c) 1983, 1993, 1994\n\
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)lpd.c 8.7 (Berkeley) 5/10/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: lpd.c,v 1.19 1999/12/23 02:10:07 mjl Exp $");
|
||||
__RCSID("$NetBSD: lpd.c,v 1.20 2000/01/27 05:39:50 itojun Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
@ -116,9 +116,10 @@ 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((char *));
|
||||
static void usage __P((void));
|
||||
static int *socksetup __P((int, int));
|
||||
|
||||
uid_t uid, euid;
|
||||
int child_count;
|
||||
@ -128,10 +129,10 @@ main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
int f, funix, finet, options, fromlen;
|
||||
int f, funix, *finet, options, fromlen;
|
||||
fd_set defreadfds;
|
||||
struct sockaddr_un un, fromunix;
|
||||
struct sockaddr_in sin, frominet;
|
||||
struct sockaddr_storage frominet;
|
||||
int omask, lfd, errs, i;
|
||||
int child_max = 32; /* more then enough to hose the system */
|
||||
|
||||
@ -242,31 +243,15 @@ main(argc, argv)
|
||||
FD_SET(funix, &defreadfds);
|
||||
listen(funix, 5);
|
||||
if (!sflag)
|
||||
finet = socket(AF_INET, SOCK_STREAM, 0);
|
||||
finet = socksetup(PF_UNSPEC, options);
|
||||
else
|
||||
finet = -1; /* pretend we couldn't open TCP socket. */
|
||||
if (finet >= 0) {
|
||||
struct servent *sp;
|
||||
finet = NULL; /* pretend we couldn't open TCP socket. */
|
||||
|
||||
if (options & SO_DEBUG)
|
||||
if (setsockopt(finet, SOL_SOCKET, SO_DEBUG, 0, 0) < 0) {
|
||||
syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m");
|
||||
mcleanup(0);
|
||||
}
|
||||
sp = getservbyname("printer", "tcp");
|
||||
if (sp == NULL) {
|
||||
syslog(LOG_ERR, "printer/tcp: unknown service");
|
||||
mcleanup(0);
|
||||
if (finet) {
|
||||
for (i = 1; i <= *finet; i++) {
|
||||
FD_SET(finet[i], &defreadfds);
|
||||
listen(finet[i], 5);
|
||||
}
|
||||
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);
|
||||
}
|
||||
/*
|
||||
* Main loop: accept, do a request, continue.
|
||||
@ -302,10 +287,12 @@ main(argc, argv)
|
||||
domain = AF_LOCAL, fromlen = sizeof(fromunix);
|
||||
s = accept(funix,
|
||||
(struct sockaddr *)&fromunix, &fromlen);
|
||||
} else /* if (FD_ISSET(finet, &readfds)) */ {
|
||||
domain = AF_INET, fromlen = sizeof(frominet);
|
||||
s = accept(finet,
|
||||
(struct sockaddr *)&frominet, &fromlen);
|
||||
} 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)
|
||||
@ -321,13 +308,15 @@ main(argc, argv)
|
||||
signal(SIGQUIT, SIG_IGN);
|
||||
signal(SIGTERM, SIG_IGN);
|
||||
(void)close(funix);
|
||||
if (!sflag)
|
||||
(void)close(finet);
|
||||
if (!sflag && 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();
|
||||
@ -372,7 +361,7 @@ int requ[MAXREQUESTS]; /* job number of spool entries */
|
||||
int requests; /* # of spool requests */
|
||||
char *person; /* name of person doing lprm */
|
||||
|
||||
char fromb[MAXHOSTNAMELEN]; /* buffer for client's machine name */
|
||||
char fromb[NI_MAXHOST]; /* buffer for client's machine name */
|
||||
char cbuf[BUFSIZ]; /* command line buffer */
|
||||
char *cmdnames[] = {
|
||||
"null",
|
||||
@ -564,46 +553,67 @@ ckqueue(cap)
|
||||
*/
|
||||
static void
|
||||
chkhost(f)
|
||||
struct sockaddr_in *f;
|
||||
struct sockaddr *f;
|
||||
{
|
||||
struct hostent *hp;
|
||||
struct addrinfo hints, *res, *r;
|
||||
FILE *hostf;
|
||||
int first = 1, good = 0;
|
||||
char host[NI_MAXHOST], ip[NI_MAXHOST];
|
||||
char serv[NI_MAXSERV];
|
||||
int error;
|
||||
|
||||
f->sin_port = ntohs(f->sin_port);
|
||||
if (f->sin_family != AF_INET || f->sin_port >= IPPORT_RESERVED)
|
||||
error = getnameinfo(f, f->sa_len, NULL, 0, serv, sizeof(serv),
|
||||
NI_NUMERICSERV);
|
||||
if (error || atoi(serv) >= IPPORT_RESERVED)
|
||||
fatal("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("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);
|
||||
if (error)
|
||||
fatal("Host name for your address unknown");
|
||||
else
|
||||
fatal("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;
|
||||
|
||||
/* 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");
|
||||
|
||||
/* Check for spoof, ala rlogind */
|
||||
hp = gethostbyname(fromb);
|
||||
if (!hp)
|
||||
fatal("hostname for your address (%s) unknown",
|
||||
inet_ntoa(f->sin_addr));
|
||||
for (; good == 0 && hp->h_addr_list[0] != NULL; hp->h_addr_list++) {
|
||||
if (!memcmp(hp->h_addr_list[0], (caddr_t)&f->sin_addr,
|
||||
sizeof(f->sin_addr)))
|
||||
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))
|
||||
good = 1;
|
||||
}
|
||||
if (res)
|
||||
freeaddrinfo(res);
|
||||
if (good == 0)
|
||||
fatal("address for your hostname (%s) not matched",
|
||||
inet_ntoa(f->sin_addr));
|
||||
fatal("address for your hostname (%s) not matched", host);
|
||||
setproctitle("serving %s", from);
|
||||
hostf = fopen(_PATH_HOSTSEQUIV, "r");
|
||||
again:
|
||||
if (hostf) {
|
||||
if (__ivaliduser(hostf, f->sin_addr.s_addr,
|
||||
DUMMY, DUMMY) == 0) {
|
||||
if (__ivaliduser_sa(hostf, f, DUMMY, DUMMY) == 0) {
|
||||
(void)fclose(hostf);
|
||||
return;
|
||||
}
|
||||
@ -626,3 +636,68 @@ usage()
|
||||
fprintf(stderr, "usage: %s [-d] [-l]\n", __progname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* 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 *
|
||||
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, (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_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");
|
||||
close (*s);
|
||||
continue;
|
||||
}
|
||||
*socks = *socks + 1;
|
||||
s++;
|
||||
}
|
||||
|
||||
if (res)
|
||||
freeaddrinfo(res);
|
||||
|
||||
if (*socks == 0) {
|
||||
syslog(LOG_ERR, "Couldn't bind to any socket");
|
||||
free(socks);
|
||||
mcleanup(0);
|
||||
}
|
||||
return(socks);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user