summaryrefslogtreecommitdiffstats
path: root/usr.sbin
diff options
context:
space:
mode:
authorume <ume@FreeBSD.org>2003-11-14 17:34:08 +0000
committerume <ume@FreeBSD.org>2003-11-14 17:34:08 +0000
commit1cc5ee037b36b56016d408fee3bd873ba27cfa3d (patch)
treefb19cd0cd36a6f4dd9086dce6e3848ffb6d89f51 /usr.sbin
parentb0479caf614810b424cbb8e80b47db2da6b2ca71 (diff)
downloadFreeBSD-src-1cc5ee037b36b56016d408fee3bd873ba27cfa3d.zip
FreeBSD-src-1cc5ee037b36b56016d408fee3bd873ba27cfa3d.tar.gz
- poll(2) support.
- simplify by strdup. - set ai_protocol in hints to TCP. - g/c FAITH_NS (no description, not maintained for years) - warn if connection from IPv4 mapped is reached. - IPV6_V6ONLY if possible. - unifdef -UFAITH4. - drop rsh/rlogin support. - deal with negative return value from wait3. Obtained from: KAME
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/faithd/Makefile4
-rw-r--r--usr.sbin/faithd/README5
-rw-r--r--usr.sbin/faithd/faithd.896
-rw-r--r--usr.sbin/faithd/faithd.c225
-rw-r--r--usr.sbin/faithd/faithd.h4
-rw-r--r--usr.sbin/faithd/ftp.c592
-rw-r--r--usr.sbin/faithd/prefix.c31
-rw-r--r--usr.sbin/faithd/rsh.c212
-rw-r--r--usr.sbin/faithd/tcp.c25
-rw-r--r--usr.sbin/faithd/test/faithd.rb2
10 files changed, 439 insertions, 757 deletions
diff --git a/usr.sbin/faithd/Makefile b/usr.sbin/faithd/Makefile
index 29634c3..3d663b8 100644
--- a/usr.sbin/faithd/Makefile
+++ b/usr.sbin/faithd/Makefile
@@ -16,8 +16,8 @@
PROG= faithd
MAN= faithd.8
-SRCS= faithd.c tcp.c ftp.c rsh.c prefix.c
+SRCS= faithd.c tcp.c ftp.c prefix.c
-#CFLAGS+= -DFAITH4
+CFLAGS= -DHAVE_POLL_H
.include <bsd.prog.mk>
diff --git a/usr.sbin/faithd/README b/usr.sbin/faithd/README
index af0bfed..6628bf6 100644
--- a/usr.sbin/faithd/README
+++ b/usr.sbin/faithd/README
@@ -1,9 +1,10 @@
Configuring FAITH IPv6-to-IPv4 TCP relay
Kazu Yamamoto and Jun-ichiro itojun Hagino
-$KAME: README,v 1.8 2001/09/05 03:04:20 itojun Exp $
+$KAME: README,v 1.10 2003/01/06 21:40:33 sumikawa Exp $
$FreeBSD$
+
Introduction
============
@@ -73,8 +74,6 @@ The following example assumes:
More examples:
- # faithd login /usr/libexec/rlogin rlogind
- # faithd shell /usr/libexec/rshd rshd
# faithd ftpd /usr/libexec/ftpd ftpd -l
# faithd sshd
diff --git a/usr.sbin/faithd/faithd.8 b/usr.sbin/faithd/faithd.8
index 177396b..66de665 100644
--- a/usr.sbin/faithd/faithd.8
+++ b/usr.sbin/faithd/faithd.8
@@ -1,4 +1,4 @@
-.\" $KAME: faithd.8,v 1.33 2001/09/05 03:04:20 itojun Exp $
+.\" $KAME: faithd.8,v 1.37 2002/05/09 14:21:23 itojun Exp $
.\"
.\" Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
.\" All rights reserved.
@@ -41,10 +41,12 @@
.Op Fl f Ar configfile
.Ar service
.Op Ar serverpath Op Ar serverargs
+.Nm ""
.Sh DESCRIPTION
The
.Nm
-utility provides IPv6-to-IPv4 TCP relay. It
+utility provides IPv6-to-IPv4 TCP relay.
+.Nm
must be used on an IPv4/v6 dual stack router.
.Pp
When
@@ -65,7 +67,7 @@ destination.
For example, if
.Li 3ffe:0501:4819:ffff::
is reserved for
-.Nm ,
+.Nm Ns ,
and the
.Tn TCPv6
destination address is
@@ -116,7 +118,6 @@ at
.Pa http://www.vermicelli.pasta.cs.uit.no/ipv6/software.html .
Make sure you do not propagate translated DNS records to normal DNS cloud,
it is highly harmful.
-.Pp
.Ss Daemon mode
When
.Nm
@@ -147,7 +148,7 @@ or other standard mechanisms.
By specifying
.Ar serverpath
to
-.Nm ,
+.Nm Ns ,
you can run local daemons on the router.
The
.Nm
@@ -172,8 +173,6 @@ Use privileged TCP port number as source port,
for IPv4 TCP connection toward final destination.
For relaying
.Xr ftp 1
-and
-.Xr rlogin 1 ,
this flag is not necessary as special program code is supplied.
.El
.Pp
@@ -184,9 +183,7 @@ It is capable of emulating TCP half close as well.
The
.Nm
utility includes special support for protocols used by
-.Xr ftp 1
-and
-.Xr rlogin 1 .
+.Xr ftp 1 .
When translating FTP protocol,
.Nm
translates network level addresses in
@@ -194,18 +191,11 @@ translates network level addresses in
and
.Li PASV/LPSV/EPSV
commands.
-For RLOGIN protocol,
-.Nm
-will relay back connection from
-.Xr rlogind 8
-on the server to
-.Xr rlogin 1
-on client.
.Pp
Inactive sessions will be disconnected in 30 minutes,
to avoid stale sessions from chewing up resources.
This may be inappropriate for some of the services
-(should this be configurable?).
+.Pq should this be configurable? .
.Ss inetd mode
When
.Nm
@@ -243,10 +233,12 @@ To prevent malicious accesses,
implements a simple address-based access control.
With
.Pa /etc/faithd.conf
-(or
+.Po
+or
.Ar configfile
specified by
-.Fl f ) ,
+.Fl f
+.Pc ,
.Nm
will avoid relaying unwanted traffic.
The
@@ -254,35 +246,48 @@ The
contains directives with the following format:
.Bl -bullet
.It
-.Ar src Ns / Ns Ar slen Cm deny Ar dst Ns / Ns Ar dlen
+.Xo
+.Ic Ar src/slen Li deny Ar dst/dlen
+.Xc
.Pp
If the source address of a query matches
-.Ar src Ns / Ns Ar slen ,
+.Ar src/slen ,
and the translated destination address matches
-.Ar dst Ns / Ns Ar dlen ,
+.Ar dst/dlen ,
deny the connection.
.It
-.Ar src Ns / Ns Ar slen Cm permit Ar dst Ns / Ns Ar dlen
+.Xo
+.Ic Ar src/slen Li permit Ar dst/dlen
+.Xc
.Pp
If the source address of a query matches
-.Ar src Ns / Ns Ar slen ,
+.Ar src/slen ,
and the translated destination address matches
-.Ar dst Ns / Ns Ar dlen ,
+.Ar dst/dlen ,
permit the connection.
.El
.Pp
The directives are evaluated in sequence,
and the first matching entry will be effective.
If there is no match
-(if we reach the end of the ruleset)
+.Pq if we reach the end of the ruleset
the traffic will be denied.
.Pp
With inetd mode,
traffic may be filtered by using access control functionality in
.Xr inetd 8 .
+.Sh RETURN VALUES
+.Nm
+exits with
+.Dv EXIT_SUCCESS
+.Pq 0
+on success, and
+.Dv EXIT_FAILURE
+.Pq 1
+on error.
.Sh EXAMPLES
Before invoking
-.Nm ,
+.Nm Ns ,
.Xr faith 4
interface has to be configured properly.
.Bd -literal -offset
@@ -320,26 +325,19 @@ If you would like to pass extra arguments to the local daemon:
Here are some other examples.
You may need
.Fl p
-to translate rsh/rlogin services.
+if the service checks the source port range.
.Bd -literal -offset
# faithd ssh
-# faithd login /usr/libexec/rlogin rlogind
-# faithd shell /usr/libexec/rshd rshd
+# faithd telnet /usr/libexec/telnetd telnetd
.Ed
-.Pp
-However, you should be careful when translating rlogin or rsh
-connections.
-See
-.Sx SECURITY CONSIDERATIONS
-for more details.
.Ss inetd mode samples
Add the following lines into
.Xr inetd.conf 5 .
Syntax may vary depending upon your operating system.
.Bd -literal -offset
-telnet stream tcp6/faith nowait root /usr/sbin/faithd telnetd
-ftp stream tcp6/faith nowait root /usr/sbin/faithd ftpd -l
-ssh stream tcp6/faith nowait root /usr/sbin/faithd /usr/sbin/sshd -i
+telnet stream tcp6/faith nowait root faithd telnetd
+ftp stream tcp6/faith nowait root faithd ftpd -l
+ssh stream tcp6/faith nowait root faithd /usr/sbin/sshd -i
.Ed
.Pp
.Xr inetd 8
@@ -370,16 +368,6 @@ setting.
3ffe:501:ffff::/48 deny 127.0.0.0/8
3ffe:501:ffff::/48 permit 0.0.0.0/0
.Ed
-.Sh RETURN VALUES
-The
-.Nm
-utility exits with
-.Dv EXIT_SUCCESS
-.Pq 0
-on success, and
-.Dv EXIT_FAILURE
-.Pq 1
-on error.
.Sh SEE ALSO
.Xr faith 4 ,
.Xr route 8 ,
@@ -403,11 +391,9 @@ IPv6 and IPsec support based on the KAME Project (http://www.kame.net/) stack
was initially integrated into
.Fx 4.0
.Sh SECURITY CONSIDERATIONS
-It is very insecure to use
-.Xr rhosts 5
-and other IP-address based authentication, for connections relayed by
-.Nm
-(and any other TCP relaying services).
+It is very insecure to use IP-address based authentication, for connections relayed by
+.Nm Ns ,
+and any other TCP relaying services.
.Pp
Administrators are advised to limit accesses to
.Nm
diff --git a/usr.sbin/faithd/faithd.c b/usr.sbin/faithd/faithd.c
index 856f24a..3df90a5 100644
--- a/usr.sbin/faithd/faithd.c
+++ b/usr.sbin/faithd/faithd.c
@@ -1,4 +1,4 @@
-/* $KAME: faithd.c,v 1.46 2002/01/24 16:40:42 sumikawa Exp $ */
+/* $KAME: faithd.c,v 1.67 2003/10/16 05:26:21 itojun Exp $ */
/*
* Copyright (C) 1997 and 1998 WIDE Project.
@@ -46,10 +46,11 @@
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/ioctl.h>
-#ifdef __FreeBSD__
#include <libutil.h>
-#endif
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#endif
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
@@ -74,14 +75,6 @@
#include <netdb.h>
#include <ifaddrs.h>
-#ifdef FAITH4
-#include <resolv.h>
-#include <arpa/nameser.h>
-#ifndef FAITH_NS
-#define FAITH_NS "FAITH_NS"
-#endif
-#endif
-
#include "faithd.h"
#include "prefix.h"
@@ -90,11 +83,13 @@ char *serverarg[MAXARGV + 1];
static char *faithdname = NULL;
char logname[BUFSIZ];
char procname[BUFSIZ];
+
struct myaddrs {
struct myaddrs *next;
struct sockaddr *addr;
};
struct myaddrs *myaddrs = NULL;
+
static const char *service;
#ifdef USE_ROUTE
static int sockfd = 0;
@@ -111,9 +106,6 @@ static void play_service __P((int));
static void play_child __P((int, struct sockaddr *));
static int faith_prefix __P((struct sockaddr *));
static int map6to4 __P((struct sockaddr_in6 *, struct sockaddr_in *));
-#ifdef FAITH4
-static int map4to6 __P((struct sockaddr_in *, struct sockaddr_in6 *));
-#endif
static void sig_child __P((int));
static void sig_terminate __P((int));
static void start_daemon __P((void));
@@ -151,7 +143,7 @@ inetd_main(int argc, char **argv)
char path[MAXPATHLEN];
struct sockaddr_storage me;
struct sockaddr_storage from;
- int melen, fromlen;
+ socklen_t melen, fromlen;
int i;
int error;
const int on = 1;
@@ -228,11 +220,8 @@ daemon_main(int argc, char **argv)
int s_wld, error, i, serverargc, on = 1;
int family = AF_INET6;
int c;
-#ifdef FAITH_NS
- char *ns;
-#endif /* FAITH_NS */
- while ((c = getopt(argc, argv, "df:p46")) != -1) {
+ while ((c = getopt(argc, argv, "df:p")) != -1) {
switch (c) {
case 'd':
dflag++;
@@ -243,14 +232,6 @@ daemon_main(int argc, char **argv)
case 'p':
pflag++;
break;
-#ifdef FAITH4
- case '4':
- family = AF_INET;
- break;
- case '6':
- family = AF_INET6;
- break;
-#endif
default:
usage();
/*NOTREACHED*/
@@ -264,23 +245,6 @@ daemon_main(int argc, char **argv)
/*NOTREACHED*/
}
-#ifdef FAITH_NS
- if ((ns = getenv(FAITH_NS)) != NULL) {
- struct sockaddr_storage ss;
- struct addrinfo hints, *res;
- char serv[NI_MAXSERV];
-
- memset(&ss, 0, sizeof(ss));
- memset(&hints, 0, sizeof(hints));
- snprintf(serv, sizeof(serv), "%u", NAMESERVER_PORT);
- hints.ai_flags = AI_NUMERICHOST;
- if (getaddrinfo(ns, serv, &hints, &res) == 0) {
- res_init();
- memcpy(&_res_ext.nsaddr, res->ai_addr, res->ai_addrlen);
- _res.nscount = 1;
- }
- }
-#endif /* FAITH_NS */
#ifdef USE_ROUTE
grab_myaddrs();
@@ -295,11 +259,13 @@ daemon_main(int argc, char **argv)
if (serverargc >= MAXARGV)
exit_stderr("too many arguments");
- serverpath = malloc(strlen(argv[NUMPRG]) + 1);
- strcpy(serverpath, argv[NUMPRG]);
+ serverpath = strdup(argv[NUMPRG]);
+ if (!serverpath)
+ exit_stderr("not enough core");
for (i = 0; i < serverargc; i++) {
- serverarg[i] = malloc(strlen(argv[i + NUMARG]) + 1);
- strcpy(serverarg[i], argv[i + NUMARG]);
+ serverarg[i] = strdup(argv[i + NUMARG]);
+ if (!serverarg[i])
+ exit_stderr("not enough core");
}
serverarg[i] = NULL;
/* fall throuth */
@@ -308,6 +274,8 @@ daemon_main(int argc, char **argv)
break;
}
+ start_daemon();
+
/*
* Opening wild card socket for this service.
*/
@@ -316,7 +284,7 @@ daemon_main(int argc, char **argv)
hints.ai_flags = AI_PASSIVE;
hints.ai_family = family;
hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = 0;
+ hints.ai_protocol = IPPROTO_TCP; /* SCTP? */
error = getaddrinfo(NULL, service, &hints, &res);
if (error)
exit_failure("getaddrinfo: %s", gai_strerror(error));
@@ -333,16 +301,6 @@ daemon_main(int argc, char **argv)
strerror(errno));
}
#endif
-#ifdef FAITH4
-#ifdef IP_FAITH
- if (res->ai_family == AF_INET) {
- error = setsockopt(s_wld, IPPROTO_IP, IP_FAITH, &on, sizeof(on));
- if (error == -1)
- exit_failure("setsockopt(IP_FAITH): %s",
- strerror(errno));
- }
-#endif
-#endif /* FAITH4 */
error = setsockopt(s_wld, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
if (error == -1)
@@ -352,6 +310,12 @@ daemon_main(int argc, char **argv)
if (error == -1)
exit_failure("setsockopt(SO_OOBINLINE): %s", strerror(errno));
+#ifdef IPV6_V6ONLY
+ error = setsockopt(s_wld, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on));
+ if (error == -1)
+ exit_failure("setsockopt(IPV6_V6ONLY): %s", strerror(errno));
+#endif
+
error = bind(s_wld, (struct sockaddr *)res->ai_addr, res->ai_addrlen);
if (error == -1)
exit_failure("bind: %s", strerror(errno));
@@ -372,8 +336,6 @@ daemon_main(int argc, char **argv)
* Everything is OK.
*/
- start_daemon();
-
snprintf(logname, sizeof(logname), "faithd %s", service);
snprintf(procname, sizeof(procname), "accepting port %s", service);
openlog(logname, LOG_PID | LOG_NOWAIT, LOG_DAEMON);
@@ -388,12 +350,16 @@ static void
play_service(int s_wld)
{
struct sockaddr_storage srcaddr;
- int len;
+ socklen_t len;
int s_src;
pid_t child_pid;
+#ifdef HAVE_POLL_H
+ struct pollfd pfd[2];
+#else
fd_set rfds;
- int error;
int maxfd;
+#endif
+ int error;
/*
* Wait, accept, fork, faith....
@@ -401,17 +367,37 @@ play_service(int s_wld)
again:
setproctitle("%s", procname);
+#ifdef HAVE_POLL_H
+ pfd[0].fd = s_wld;
+ pfd[0].events = POLLIN;
+ pfd[1].fd = -1;
+ pfd[1].revents = 0;
+#else
FD_ZERO(&rfds);
+ if (s_wld >= FD_SETSIZE)
+ exit_failure("descriptor too big");
FD_SET(s_wld, &rfds);
maxfd = s_wld;
+#endif
#ifdef USE_ROUTE
if (sockfd) {
+#ifdef HAVE_POLL_H
+ pfd[1].fd = sockfd;
+ pfd[1].events = POLLIN;
+#else
+ if (sockfd >= FD_SETSIZE)
+ exit_failure("descriptor too big");
FD_SET(sockfd, &rfds);
maxfd = (maxfd < sockfd) ? sockfd : maxfd;
+#endif
}
#endif
+#ifdef HAVE_POLL_H
+ error = poll(pfd, sizeof(pfd)/sizeof(pfd[0]), INFTIM);
+#else
error = select(maxfd + 1, &rfds, NULL, NULL, NULL);
+#endif
if (error < 0) {
if (errno == EINTR)
goto again;
@@ -420,23 +406,38 @@ again:
}
#ifdef USE_ROUTE
- if (FD_ISSET(sockfd, &rfds)) {
+#ifdef HAVE_POLL_H
+ if (pfd[1].revents & POLLIN)
+#else
+ if (FD_ISSET(sockfd, &rfds))
+#endif
+ {
update_myaddrs();
}
#endif
- if (FD_ISSET(s_wld, &rfds)) {
+#ifdef HAVE_POLL_H
+ if (pfd[0].revents & POLLIN)
+#else
+ if (FD_ISSET(s_wld, &rfds))
+#endif
+ {
len = sizeof(srcaddr);
- s_src = accept(s_wld, (struct sockaddr *)&srcaddr,
- &len);
+ s_src = accept(s_wld, (struct sockaddr *)&srcaddr, &len);
if (s_src < 0) {
if (errno == ECONNABORTED)
goto again;
exit_failure("socket: %s", strerror(errno));
/*NOTREACHED*/
}
+ if (srcaddr.ss_family == AF_INET6 &&
+ IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&srcaddr)->sin6_addr)) {
+ close(s_src);
+ syslog(LOG_ERR, "connection from IPv4 mapped address?");
+ goto again;
+ }
child_pid = fork();
-
+
if (child_pid == 0) {
/* child process */
close(s_wld);
@@ -463,7 +464,7 @@ play_child(int s_src, struct sockaddr *srcaddr)
char src[NI_MAXHOST];
char dst6[NI_MAXHOST];
char dst4[NI_MAXHOST];
- int len = sizeof(dstaddr6);
+ socklen_t len = sizeof(dstaddr6);
int s_dst, error, hport, nresvport, on = 1;
struct timeval tv;
struct sockaddr *sa4;
@@ -473,7 +474,7 @@ play_child(int s_src, struct sockaddr *srcaddr)
tv.tv_usec = 0;
getnameinfo(srcaddr, srcaddr->sa_len,
- src, sizeof(src), NULL, 0, NI_NUMERICHOST);
+ src, sizeof(src), NULL, 0, NI_NUMERICHOST);
syslog(LOG_INFO, "accepted a client from %s", src);
error = getsockname(s_src, (struct sockaddr *)&dstaddr6, &len);
@@ -483,7 +484,7 @@ play_child(int s_src, struct sockaddr *srcaddr)
}
getnameinfo((struct sockaddr *)&dstaddr6, len,
- dst6, sizeof(dst6), NULL, 0, NI_NUMERICHOST);
+ dst6, sizeof(dst6), NULL, 0, NI_NUMERICHOST);
syslog(LOG_INFO, "the client is connecting to %s", dst6);
if (!faith_prefix((struct sockaddr *)&dstaddr6)) {
@@ -522,17 +523,6 @@ play_child(int s_src, struct sockaddr *srcaddr)
}
syslog(LOG_INFO, "translating from v6 to v4");
break;
-#ifdef FAITH4
- case AF_INET:
- if (!map4to6((struct sockaddr_in *)&dstaddr6,
- (struct sockaddr_in6 *)&dstaddr4)) {
- close(s_src);
- exit_failure("map4to6 failed");
- /*NOTREACHED*/
- }
- syslog(LOG_INFO, "translating from v4 to v6");
- break;
-#endif
default:
close(s_src);
exit_failure("family not supported");
@@ -541,7 +531,7 @@ play_child(int s_src, struct sockaddr *srcaddr)
sa4 = (struct sockaddr *)&dstaddr4;
getnameinfo(sa4, sa4->sa_len,
- dst4, sizeof(dst4), NULL, 0, NI_NUMERICHOST);
+ dst4, sizeof(dst4), NULL, 0, NI_NUMERICHOST);
conf = config_match(srcaddr, sa4);
if (!conf || !conf->permit) {
@@ -565,18 +555,10 @@ play_child(int s_src, struct sockaddr *srcaddr)
else /* AF_INET */
hport = ntohs(((struct sockaddr_in *)&dstaddr4)->sin_port);
- switch (hport) {
- case RLOGIN_PORT:
- case RSH_PORT:
+ if (pflag)
s_dst = rresvport_af(&nresvport, sa4->sa_family);
- break;
- default:
- if (pflag)
- s_dst = rresvport_af(&nresvport, sa4->sa_family);
- else
- s_dst = socket(sa4->sa_family, SOCK_STREAM, 0);
- break;
- }
+ else
+ s_dst = socket(sa4->sa_family, SOCK_STREAM, 0);
if (s_dst < 0) {
exit_failure("socket: %s", strerror(errno));
/*NOTREACHED*/
@@ -617,15 +599,6 @@ play_child(int s_src, struct sockaddr *srcaddr)
case FTP_PORT:
ftp_relay(s_src, s_dst);
break;
- case RSH_PORT:
- syslog(LOG_WARNING,
- "WARINNG: it is insecure to relay rsh port");
- rsh_relay(s_src, s_dst);
- break;
- case RLOGIN_PORT:
- syslog(LOG_WARNING,
- "WARINNG: it is insecure to relay rlogin port");
- /*FALLTHROUGH*/
default:
tcp_relay(s_src, s_dst, service);
break;
@@ -657,7 +630,7 @@ faith_prefix(struct sockaddr *dst)
}
if (memcmp(dst, &faith_prefix,
- sizeof(struct in6_addr) - sizeof(struct in_addr) == 0) {
+ sizeof(struct in6_addr) - sizeof(struct in_addr) == 0) {
return 1;
}
return 0;
@@ -727,39 +700,6 @@ map6to4(struct sockaddr_in6 *dst6, struct sockaddr_in *dst4)
return 1;
}
-#ifdef FAITH4
-/* 0: non faith, 1: faith */
-static int
-map4to6(struct sockaddr_in *dst4, struct sockaddr_in6 *dst6)
-{
- char host[NI_MAXHOST];
- char serv[NI_MAXSERV];
- struct addrinfo hints, *res;
- int ai_errno;
-
- if (getnameinfo((struct sockaddr *)dst4, dst4->sin_len, host, sizeof(host),
- serv, sizeof(serv), NI_NAMEREQD|NI_NUMERICSERV) != 0)
- return 0;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_flags = 0;
- hints.ai_family = AF_INET6;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = 0;
-
- if ((ai_errno = getaddrinfo(host, serv, &hints, &res)) != 0) {
- syslog(LOG_INFO, "%s %s: %s", host, serv,
- gai_strerror(ai_errno));
- return 0;
- }
-
- memcpy(dst6, res->ai_addr, res->ai_addrlen);
-
- freeaddrinfo(res);
-
- return 1;
-}
-#endif /* FAITH4 */
static void
sig_child(int sig)
@@ -767,9 +707,10 @@ sig_child(int sig)
int status;
pid_t pid;
- pid = wait3(&status, WNOHANG, (struct rusage *)0);
- if (pid && WEXITSTATUS(status))
- syslog(LOG_WARNING, "child %d exit status 0x%x", pid, status);
+ while ((pid = wait3(&status, WNOHANG, (struct rusage *)0)) > 0)
+ if (WEXITSTATUS(status))
+ syslog(LOG_WARNING, "child %ld exit status 0x%x",
+ (long)pid, status);
}
void
@@ -894,8 +835,8 @@ grab_myaddrs()
if (dflag) {
char hbuf[NI_MAXHOST];
getnameinfo(p->addr, p->addr->sa_len,
- hbuf, sizeof(hbuf), NULL, 0,
- NI_NUMERICHOST);
+ hbuf, sizeof(hbuf), NULL, 0,
+ NI_NUMERICHOST);
syslog(LOG_INFO, "my interface: %s %s", hbuf,
ifa->ifa_name);
}
diff --git a/usr.sbin/faithd/faithd.h b/usr.sbin/faithd/faithd.h
index 0efb2b8..f422432 100644
--- a/usr.sbin/faithd/faithd.h
+++ b/usr.sbin/faithd/faithd.h
@@ -1,4 +1,4 @@
-/* $KAME: faithd.h,v 1.8 2001/09/05 03:04:21 itojun Exp $ */
+/* $KAME: faithd.h,v 1.9 2002/05/09 09:41:24 itojun Exp $ */
/*
* Copyright (C) 1997 and 1998 WIDE Project.
@@ -38,8 +38,6 @@ extern void tcp_relay __P((int, int, const char *));
extern void ftp_relay __P((int, int));
extern int ftp_active __P((int, int, int *, int *));
extern int ftp_passive __P((int, int, int *, int *));
-extern void rsh_relay __P((int, int));
-extern void rsh_dual_relay __P((int, int));
extern void exit_success __P((const char *, ...))
__attribute__((__format__(__printf__, 1, 2)));
extern void exit_failure __P((const char *, ...))
diff --git a/usr.sbin/faithd/ftp.c b/usr.sbin/faithd/ftp.c
index 5664681..6ceb24d 100644
--- a/usr.sbin/faithd/ftp.c
+++ b/usr.sbin/faithd/ftp.c
@@ -1,4 +1,4 @@
-/* $KAME: ftp.c,v 1.11 2001/07/02 14:36:49 itojun Exp $ */
+/* $KAME: ftp.c,v 1.23 2003/08/19 21:20:33 itojun Exp $ */
/*
* Copyright (C) 1997 and 1998 WIDE Project.
@@ -42,6 +42,9 @@
#include <string.h>
#include <syslog.h>
#include <unistd.h>
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#endif
#include <errno.h>
#include <ctype.h>
@@ -62,11 +65,7 @@ static struct sockaddr_storage data4; /* server data address */
static struct sockaddr_storage data6; /* client data address */
static int epsvall = 0;
-#ifdef FAITH4
-enum state { NONE, LPRT, EPRT, PORT, LPSV, EPSV, PASV };
-#else
enum state { NONE, LPRT, EPRT, LPSV, EPSV };
-#endif
static int ftp_activeconn __P((void));
static int ftp_passiveconn __P((void));
@@ -77,7 +76,11 @@ static int ftp_copycommand __P((int, int, enum state *));
void
ftp_relay(int ctl6, int ctl4)
{
+#ifdef HAVE_POLL_H
+ struct pollfd pfd[6];
+#else
fd_set readfds;
+#endif
int error;
enum state state = NONE;
struct timeval tv;
@@ -85,25 +88,90 @@ ftp_relay(int ctl6, int ctl4)
syslog(LOG_INFO, "starting ftp control connection");
for (;;) {
+#ifdef HAVE_POLL_H
+ pfd[0].fd = ctl4;
+ pfd[0].events = POLLIN;
+ pfd[1].fd = ctl6;
+ pfd[1].events = POLLIN;
+ if (0 <= port4) {
+ pfd[2].fd = port4;
+ pfd[2].events = POLLIN;
+ } else
+ pfd[2].fd = -1;
+ if (0 <= port6) {
+ pfd[3].fd = port6;
+ pfd[3].events = POLLIN;
+ } else
+ pfd[3].fd = -1;
+#if 0
+ if (0 <= wport4) {
+ pfd[4].fd = wport4;
+ pfd[4].events = POLLIN;
+ } else
+ pfd[4].fd = -1;
+ if (0 <= wport6) {
+ pfd[5].fd = wport4;
+ pfd[5].events = POLLIN;
+ } else
+ pfd[5].fd = -1;
+#else
+ pfd[4].fd = pfd[5].fd = -1;
+ pfd[4].events = pfd[5].events = 0;
+#endif
+#else
+ int maxfd = 0;
+
FD_ZERO(&readfds);
+ if (ctl4 >= FD_SETSIZE)
+ exit_failure("descriptor too big");
FD_SET(ctl4, &readfds);
+ maxfd = ctl4;
+ if (ctl6 >= FD_SETSIZE)
+ exit_failure("descriptor too big");
FD_SET(ctl6, &readfds);
- if (0 <= port4)
+ maxfd = (ctl6 > maxfd) ? ctl6 : maxfd;
+ if (0 <= port4) {
+ if (port4 >= FD_SETSIZE)
+ exit_failure("descriptor too big");
FD_SET(port4, &readfds);
- if (0 <= port6)
+ maxfd = (port4 > maxfd) ? port4 : maxfd;
+ }
+ if (0 <= port6) {
+ if (port6 >= FD_SETSIZE)
+ exit_failure("descriptor too big");
FD_SET(port6, &readfds);
+ maxfd = (port6 > maxfd) ? port6 : maxfd;
+ }
#if 0
- if (0 <= wport4)
+ if (0 <= wport4) {
+ if (wport4 >= FD_SETSIZE)
+ exit_failure("descriptor too big");
FD_SET(wport4, &readfds);
- if (0 <= wport6)
+ maxfd = (wport4 > maxfd) ? wport4 : maxfd;
+ }
+ if (0 <= wport6) {
+ if (wport6 >= FD_SETSIZE)
+ exit_failure("descriptor too big");
FD_SET(wport6, &readfds);
+ maxfd = (wport6 > maxfd) ? wport6 : maxfd;
+ }
+#endif
#endif
tv.tv_sec = FAITH_TIMEOUT;
tv.tv_usec = 0;
- error = select(256, &readfds, NULL, NULL, &tv);
- if (error == -1)
+#ifdef HAVE_POLL_H
+ error = poll(pfd, sizeof(pfd)/sizeof(pfd[0]), tv.tv_sec * 1000);
+#else
+ error = select(maxfd + 1, &readfds, NULL, NULL, &tv);
+#endif
+ if (error == -1) {
+#ifdef HAVE_POLL_H
+ exit_failure("poll: %s", strerror(errno));
+#else
exit_failure("select: %s", strerror(errno));
+#endif
+ }
else if (error == 0)
exit_failure("connection timeout");
@@ -113,7 +181,12 @@ ftp_relay(int ctl6, int ctl4)
* otherwise some of the pipe may become full and we cannot
* relay correctly.
*/
- if (FD_ISSET(ctl6, &readfds)) {
+#ifdef HAVE_POLL_H
+ if (pfd[1].revents & POLLIN)
+#else
+ if (FD_ISSET(ctl6, &readfds))
+#endif
+ {
/*
* copy control connection from the client.
* command translation is necessary.
@@ -126,9 +199,15 @@ ftp_relay(int ctl6, int ctl4)
close(ctl4);
close(ctl6);
exit_success("terminating ftp control connection");
+ /*NOTREACHED*/
}
}
- if (FD_ISSET(ctl4, &readfds)) {
+#ifdef HAVE_POLL_H
+ if (pfd[0].revents & POLLIN)
+#else
+ if (FD_ISSET(ctl4, &readfds))
+#endif
+ {
/*
* copy control connection from the server
* translation of result code is necessary.
@@ -141,14 +220,24 @@ ftp_relay(int ctl6, int ctl4)
close(ctl4);
close(ctl6);
exit_success("terminating ftp control connection");
+ /*NOTREACHED*/
}
}
- if (0 <= port4 && 0 <= port6 && FD_ISSET(port4, &readfds)) {
+#ifdef HAVE_POLL_H
+ if (0 <= port4 && 0 <= port6 && (pfd[2].revents & POLLIN))
+#else
+ if (0 <= port4 && 0 <= port6 && FD_ISSET(port4, &readfds))
+#endif
+ {
/*
* copy data connection.
* no special treatment necessary.
*/
+#ifdef HAVE_POLL_H
+ if (pfd[2].revents & POLLIN)
+#else
if (FD_ISSET(port4, &readfds))
+#endif
error = ftp_copy(port4, port6);
switch (error) {
case -1:
@@ -163,12 +252,21 @@ ftp_relay(int ctl6, int ctl4)
break;
}
}
- if (0 <= port4 && 0 <= port6 && FD_ISSET(port6, &readfds)) {
+#ifdef HAVE_POLL_H
+ if (0 <= port4 && 0 <= port6 && (pfd[3].revents & POLLIN))
+#else
+ if (0 <= port4 && 0 <= port6 && FD_ISSET(port6, &readfds))
+#endif
+ {
/*
* copy data connection.
* no special treatment necessary.
*/
+#ifdef HAVE_POLL_H
+ if (pfd[3].revents & POLLIN)
+#else
if (FD_ISSET(port6, &readfds))
+#endif
error = ftp_copy(port6, port4);
switch (error) {
case -1:
@@ -184,13 +282,23 @@ ftp_relay(int ctl6, int ctl4)
}
}
#if 0
- if (wport4 && FD_ISSET(wport4, &readfds)) {
+#ifdef HAVE_POLL_H
+ if (wport4 && (pfd[4].revents & POLLIN))
+#else
+ if (wport4 && FD_ISSET(wport4, &readfds))
+#endif
+ {
/*
* establish active data connection from the server.
*/
ftp_activeconn();
}
- if (wport6 && FD_ISSET(wport6, &readfds)) {
+#ifdef HAVE_POLL_H
+ if (wport4 && (pfd[5].revents & POLLIN))
+#else
+ if (wport6 && FD_ISSET(wport6, &readfds))
+#endif
+ {
/*
* establish passive data connection from the client.
*/
@@ -206,20 +314,37 @@ ftp_relay(int ctl6, int ctl4)
static int
ftp_activeconn()
{
- int n;
+ socklen_t n;
int error;
+#ifdef HAVE_POLL_H
+ struct pollfd pfd[1];
+#else
fd_set set;
+#endif
struct timeval timeout;
struct sockaddr *sa;
/* get active connection from server */
+#ifdef HAVE_POLL_H
+ pfd[0].fd = wport4;
+ pfd[0].events = POLLIN;
+#else
FD_ZERO(&set);
+ if (wport4 >= FD_SETSIZE)
+ exit_failure("descriptor too big");
FD_SET(wport4, &set);
+#endif
timeout.tv_sec = 120;
- timeout.tv_usec = -1;
+ timeout.tv_usec = 0;
n = sizeof(data4);
- if (select(wport4 + 1, &set, NULL, NULL, &timeout) == 0
- || (port4 = accept(wport4, (struct sockaddr *)&data4, &n)) < 0) {
+#ifdef HAVE_POLL_H
+ if (poll(pfd, sizeof(pfd)/sizeof(pfd[0]), timeout.tv_sec * 1000) == 0 ||
+ (port4 = accept(wport4, (struct sockaddr *)&data4, &n)) < 0)
+#else
+ if (select(wport4 + 1, &set, NULL, NULL, &timeout) == 0 ||
+ (port4 = accept(wport4, (struct sockaddr *)&data4, &n)) < 0)
+#endif
+ {
close(wport4);
wport4 = -1;
syslog(LOG_INFO, "active mode data connection failed");
@@ -253,20 +378,37 @@ ftp_activeconn()
static int
ftp_passiveconn()
{
- int n;
+ socklen_t len;
int error;
+#ifdef HAVE_POLL_H
+ struct pollfd pfd[1];
+#else
fd_set set;
+#endif
struct timeval timeout;
struct sockaddr *sa;
/* get passive connection from client */
+#ifdef HAVE_POLL_H
+ pfd[0].fd = wport6;
+ pfd[0].events = POLLIN;
+#else
FD_ZERO(&set);
+ if (wport6 >= FD_SETSIZE)
+ exit_failure("descriptor too big");
FD_SET(wport6, &set);
+#endif
timeout.tv_sec = 120;
timeout.tv_usec = 0;
- n = sizeof(data6);
- if (select(wport6 + 1, &set, NULL, NULL, &timeout) == 0
- || (port6 = accept(wport6, (struct sockaddr *)&data6, &n)) < 0) {
+ len = sizeof(data6);
+#ifdef HAVE_POLL_H
+ if (poll(pfd, sizeof(pfd)/sizeof(pfd[0]), timeout.tv_sec * 1000) == 0 ||
+ (port6 = accept(wport6, (struct sockaddr *)&data6, &len)) < 0)
+#else
+ if (select(wport6 + 1, &set, NULL, NULL, &timeout) == 0 ||
+ (port6 = accept(wport6, (struct sockaddr *)&data6, &len)) < 0)
+#endif
+ {
close(wport6);
wport6 = -1;
syslog(LOG_INFO, "passive mode data connection failed");
@@ -300,8 +442,7 @@ ftp_passiveconn()
static int
ftp_copy(int src, int dst)
{
- int error, atmark;
- int n;
+ int error, atmark, n;
/* OOB data handling */
error = ioctl(src, SIOCATMARK, &atmark);
@@ -338,10 +479,12 @@ ftp_copy(int src, int dst)
static int
ftp_copyresult(int src, int dst, enum state state)
{
- int error, atmark;
- int n;
+ int error, atmark, n;
+ socklen_t len;
char *param;
int code;
+ char *a, *p;
+ int i;
/* OOB data handling */
error = ioctl(src, SIOCATMARK, &atmark);
@@ -367,10 +510,6 @@ ftp_copyresult(int src, int dst, enum state state)
/*
* parse argument
*/
- {
- char *p;
- int i;
-
p = rbuf;
for (i = 0; i < 3; i++) {
if (!isdigit(*p)) {
@@ -392,7 +531,6 @@ ftp_copyresult(int src, int dst, enum state state)
param++;
if (!*param)
param = NULL;
- }
switch (state) {
case NONE:
@@ -400,15 +538,17 @@ ftp_copyresult(int src, int dst, enum state state)
if (ftp_activeconn() < 0) {
n = snprintf(rbuf, sizeof(rbuf),
"425 Cannot open data connetion\r\n");
+ if (n < 0 || n >= sizeof(rbuf))
+ n = 0;
}
}
- return n > 0 ? write(dst, rbuf, n) : n;
+ if (n)
+ write(dst, rbuf, n);
+ return n;
case LPRT:
case EPRT:
/* expecting "200 PORT command successful." */
if (code == 200) {
- char *p;
-
p = strstr(rbuf, "PORT");
if (p) {
p[0] = (state == LPRT) ? 'L' : 'E';
@@ -420,24 +560,6 @@ ftp_copyresult(int src, int dst, enum state state)
}
write(dst, rbuf, n);
return n;
-#ifdef FAITH4
- case PORT:
- /* expecting "200 EPRT command successful." */
- if (code == 200) {
- char *p;
-
- p = strstr(rbuf, "EPRT");
- if (p) {
- p[0] = 'P';
- p[1] = 'O';
- }
- } else {
- close(wport4);
- wport4 = -1;
- }
- write(dst, rbuf, n);
- return n;
-#endif
case LPSV:
case EPSV:
/*
@@ -457,7 +579,6 @@ passivefail0:
struct sockaddr_in *sin;
struct sockaddr_in6 *sin6;
u_short port;
- char *p;
/*
* PASV result -> LPSV/EPSV result
@@ -496,7 +617,11 @@ passivefail0:
passivefail:
n = snprintf(sbuf, sizeof(sbuf),
"500 could not translate from PASV\r\n");
- return n > 0 ? write(src, sbuf, n) : n;
+ if (n < 0 || n >= sizeof(sbuf))
+ n = 0;
+ if (n)
+ write(src, sbuf, n);
+ return n;
}
#ifdef IPV6_FAITH
{
@@ -524,8 +649,8 @@ passivefail:
/*
* addr from dst, port from wport6
*/
- n = sizeof(data6);
- error = getsockname(wport6, (struct sockaddr *)&data6, &n);
+ len = sizeof(data6);
+ error = getsockname(wport6, (struct sockaddr *)&data6, &len);
if (error == -1) {
close(wport6);
wport6 = -1;
@@ -534,8 +659,8 @@ passivefail:
sin6 = (struct sockaddr_in6 *)&data6;
port = sin6->sin6_port;
- n = sizeof(data6);
- error = getsockname(dst, (struct sockaddr *)&data6, &n);
+ len = sizeof(data6);
+ error = getsockname(dst, (struct sockaddr *)&data6, &len);
if (error == -1) {
close(wport6);
wport6 = -1;
@@ -545,8 +670,6 @@ passivefail:
sin6->sin6_port = port;
if (state == LPSV) {
- char *a, *p;
-
a = (char *)&sin6->sin6_addr;
p = (char *)&sin6->sin6_port;
n = snprintf(sbuf, sizeof(sbuf),
@@ -556,132 +679,24 @@ passivefail:
UC(a[8]), UC(a[9]), UC(a[10]), UC(a[11]),
UC(a[12]), UC(a[13]), UC(a[14]), UC(a[15]),
2, UC(p[0]), UC(p[1]));
- if (n > 0)
- n = write(dst, sbuf, n);
+ if (n < 0 || n >= sizeof(sbuf))
+ n = 0;
+ if (n)
+ write(dst, sbuf, n);
passivemode = 1;
return n;
} else {
n = snprintf(sbuf, sizeof(sbuf),
"229 Entering Extended Passive Mode (|||%d|)\r\n",
ntohs(sin6->sin6_port));
- if (n > 0)
- n = write(dst, sbuf, n);
+ if (n < 0 || n >= sizeof(sbuf))
+ n = 0;
+ if (n)
+ write(dst, sbuf, n);
passivemode = 1;
return n;
}
}
-#ifdef FAITH4
- case PASV:
- /* expecting "229 Entering Extended Passive Mode (|||x|)" */
- if (code != 229) {
-passivefail1:
- close(wport6);
- wport6 = -1;
- write(dst, rbuf, n);
- return n;
- }
-
- {
- u_short port;
- char *p;
- struct sockaddr_in *sin;
- struct sockaddr_in6 *sin6;
-
- /*
- * EPSV result -> PORT result
- */
- p = param;
- while (*p && *p != '(') /*)*/
- p++;
- if (!*p)
- goto passivefail1; /*XXX*/
- p++;
- n = sscanf(p, "|||%hu|", &port);
- if (n != 1)
- goto passivefail1; /*XXX*/
-
- /* keep EPRT parameter */
- n = sizeof(data4);
- error = getpeername(src, (struct sockaddr *)&data4, &n);
- if (error == -1)
- goto passivefail1; /*XXX*/
- sin6 = (struct sockaddr_in6 *)&data4;
- sin6->sin6_port = htons(port);
-
- /* get ready for passive data connection */
- memset(&data6, 0, sizeof(data6));
- sin = (struct sockaddr_in *)&data6;
- sin->sin_len = sizeof(*sin);
- sin->sin_family = AF_INET;
- wport6 = socket(sin->sin_family, SOCK_STREAM, 0);
- if (wport6 == -1) {
-passivefail2:
- n = snprintf(sbuf, sizeof(sbuf),
- "500 could not translate from EPSV\r\n");
- return n > 0 ? write(src, sbuf, n) : n;
- }
-#ifdef IP_FAITH
- {
- int on = 1;
- error = setsockopt(wport6, IPPROTO_IP, IP_FAITH,
- &on, sizeof(on));
- if (error == -1)
- exit_error("setsockopt(IP_FAITH): %s", strerror(errno));
- }
-#endif
- error = bind(wport6, (struct sockaddr *)sin, sin->sin_len);
- if (error == -1) {
- close(wport6);
- wport6 = -1;
- goto passivefail2;
- }
- error = listen(wport6, 1);
- if (error == -1) {
- close(wport6);
- wport6 = -1;
- goto passivefail2;
- }
-
- /* transmit PORT */
- /*
- * addr from dst, port from wport6
- */
- n = sizeof(data6);
- error = getsockname(wport6, (struct sockaddr *)&data6, &n);
- if (error == -1) {
- close(wport6);
- wport6 = -1;
- goto passivefail2;
- }
- sin = (struct sockaddr_in *)&data6;
- port = sin->sin_port;
-
- n = sizeof(data6);
- error = getsockname(dst, (struct sockaddr *)&data6, &n);
- if (error == -1) {
- close(wport6);
- wport6 = -1;
- goto passivefail2;
- }
- sin = (struct sockaddr_in *)&data6;
- sin->sin_port = port;
-
- {
- char *a, *p;
-
- a = (char *)&sin->sin_addr;
- p = (char *)&sin->sin_port;
- n = snprintf(sbuf, sizeof(sbuf),
-"227 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\r\n",
- UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
- UC(p[0]), UC(p[1]));
- if (n > 0)
- n = write(dst, sbuf, n);
- passivemode = 1;
- return n;
- }
- }
-#endif /* FAITH4 */
}
bad:
@@ -693,15 +708,16 @@ passivefail2:
static int
ftp_copycommand(int src, int dst, enum state *state)
{
- int error, atmark;
- int n;
+ int error, atmark, n;
+ socklen_t len;
unsigned int af, hal, ho[16], pal, po[2];
- char *a, *p;
+ char *a, *p, *q;
char cmd[5], *param;
struct sockaddr_in *sin;
struct sockaddr_in6 *sin6;
enum state nstate;
char ch;
+ int i;
/* OOB data handling */
error = ioctl(src, SIOCATMARK, &atmark);
@@ -732,10 +748,6 @@ ftp_copycommand(int src, int dst, enum state *state)
/*
* parse argument
*/
- {
- char *p, *q;
- int i;
-
p = rbuf;
q = cmd;
for (i = 0; i < 4; i++) {
@@ -759,7 +771,6 @@ ftp_copycommand(int src, int dst, enum state *state)
param++;
if (!*param)
param = NULL;
- }
*state = NONE;
@@ -778,7 +789,11 @@ ftp_copycommand(int src, int dst, enum state *state)
if (epsvall) {
n = snprintf(sbuf, sizeof(sbuf), "501 %s disallowed in EPSV ALL\r\n",
cmd);
- return n > 0 ? write(src, sbuf, n) : n;
+ if (n < 0 || n >= sizeof(sbuf))
+ n = 0;
+ if (n)
+ write(src, sbuf, n);
+ return n;
}
n = sscanf(param,
@@ -791,7 +806,11 @@ ftp_copycommand(int src, int dst, enum state *state)
if (n != 21 || af != 6 || hal != 16|| pal != 2) {
n = snprintf(sbuf, sizeof(sbuf),
"501 illegal parameter to LPRT\r\n");
- return n > 0 ? write(src, sbuf, n) : n;
+ if (n < 0 || n >= sizeof(sbuf))
+ n = 0;
+ if (n)
+ write(src, sbuf, n);
+ return n;
}
/* keep LPRT parameter */
@@ -805,13 +824,17 @@ ftp_copycommand(int src, int dst, enum state *state)
sendport:
/* get ready for active data connection */
- n = sizeof(data4);
- error = getsockname(dst, (struct sockaddr *)&data4, &n);
+ len = sizeof(data4);
+ error = getsockname(dst, (struct sockaddr *)&data4, &len);
if (error == -1) {
lprtfail:
n = snprintf(sbuf, sizeof(sbuf),
"500 could not translate to PORT\r\n");
- return n > 0 ? write(src, sbuf, n) : n;
+ if (n < 0 || n >= sizeof(sbuf))
+ n = 0;
+ if (n)
+ write(src, sbuf, n);
+ return n;
}
if (((struct sockaddr *)&data4)->sa_family != AF_INET)
goto lprtfail;
@@ -834,8 +857,8 @@ lprtfail:
}
/* transmit PORT */
- n = sizeof(data4);
- error = getsockname(wport4, (struct sockaddr *)&data4, &n);
+ len = sizeof(data4);
+ error = getsockname(wport4, (struct sockaddr *)&data4, &len);
if (error == -1) {
close(wport4);
wport4 = -1;
@@ -852,8 +875,10 @@ lprtfail:
n = snprintf(sbuf, sizeof(sbuf), "PORT %d,%d,%d,%d,%d,%d\r\n",
UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
UC(p[0]), UC(p[1]));
- if (n > 0)
- n = write(dst, sbuf, n);
+ if (n < 0 || n >= sizeof(sbuf))
+ n = 0;
+ if (n)
+ write(dst, sbuf, n);
*state = nstate;
passivemode = 0;
return n;
@@ -875,7 +900,11 @@ lprtfail:
if (epsvall) {
n = snprintf(sbuf, sizeof(sbuf), "501 %s disallowed in EPSV ALL\r\n",
cmd);
- return n > 0 ? write(src, sbuf, n) : n;
+ if (n < 0 || n >= sizeof(sbuf))
+ n = 0;
+ if (n)
+ write(src, sbuf, n);
+ return n;
}
p = param;
@@ -887,7 +916,11 @@ lprtfail:
eprtparamfail:
n = snprintf(sbuf, sizeof(sbuf),
"501 illegal parameter to EPRT\r\n");
- return n > 0 ? write(src, sbuf, n) : n;
+ if (n < 0 || n >= sizeof(sbuf))
+ n = 0;
+ if (n)
+ write(src, sbuf, n);
+ return n;
}
*p++ = '\0';
hostp = p;
@@ -907,21 +940,34 @@ eprtparamfail:
if (n != 1 || af != 2) {
n = snprintf(sbuf, sizeof(sbuf),
"501 unsupported address family to EPRT\r\n");
- return n > 0 ? write(src, sbuf, n) : n;
+ if (n < 0 || n >= sizeof(sbuf))
+ n = 0;
+ if (n)
+ write(src, sbuf, n);
+ return n;
}
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
error = getaddrinfo(hostp, portp, &hints, &res);
if (error) {
n = snprintf(sbuf, sizeof(sbuf),
"501 EPRT: %s\r\n", gai_strerror(error));
- return n > 0 ? write(src, sbuf, n) : n;
+ if (n < 0 || n >= sizeof(sbuf))
+ n = 0;
+ if (n)
+ write(src, sbuf, n);
+ return n;
}
if (res->ai_next) {
n = snprintf(sbuf, sizeof(sbuf),
"501 EPRT: %s resolved to multiple addresses\r\n", hostp);
- return n > 0 ? write(src, sbuf, n) : n;
+ if (n < 0 || n >= sizeof(sbuf))
+ n = 0;
+ if (n)
+ write(src, sbuf, n);
+ return n;
}
memcpy(&data6, res->ai_addr, res->ai_addrlen);
@@ -942,13 +988,19 @@ eprtparamfail:
if (epsvall) {
n = snprintf(sbuf, sizeof(sbuf), "501 %s disallowed in EPSV ALL\r\n",
cmd);
- return n > 0 ? write(src, sbuf, n) : n;
+ if (n < 0 || n >= sizeof(sbuf))
+ n = 0;
+ if (n)
+ write(src, sbuf, n);
+ return n;
}
/* transmit PASV */
n = snprintf(sbuf, sizeof(sbuf), "PASV\r\n");
- if (n > 0)
- n = write(dst, sbuf, n);
+ if (n < 0 || n >= sizeof(sbuf))
+ n = 0;
+ if (n)
+ write(dst, sbuf, n);
*state = LPSV;
passivemode = 0; /* to be set to 1 later */
return n;
@@ -963,8 +1015,10 @@ eprtparamfail:
wport4 = wport6 = port4 = port6 = -1;
n = snprintf(sbuf, sizeof(sbuf), "PASV\r\n");
- if (n > 0)
- n = write(dst, sbuf, n);
+ if (n < 0 || n >= sizeof(sbuf))
+ n = 0;
+ if (n)
+ write(dst, sbuf, n);
*state = EPSV;
passivemode = 0; /* to be set to 1 later */
return n;
@@ -975,120 +1029,21 @@ eprtparamfail:
*/
epsvall = 1;
n = snprintf(sbuf, sizeof(sbuf), "200 EPSV ALL command successful.\r\n");
- return n > 0 ? write(src, sbuf, n) : n;
-#ifdef FAITH4
- } else if (strcmp(cmd, "PORT") == 0 && param) {
- /*
- * PORT -> EPRT
- */
- char host[NI_MAXHOST], serv[NI_MAXSERV];
-
- nstate = PORT;
-
- close(wport4);
- close(wport6);
- close(port4);
- close(port6);
- wport4 = wport6 = port4 = port6 = -1;
-
- p = param;
- n = sscanf(p, "%u,%u,%u,%u,%u,%u",
- &ho[0], &ho[1], &ho[2], &ho[3], &po[0], &po[1]);
- if (n != 6) {
- n = snprintf(sbuf, sizeof(sbuf),
- "501 illegal parameter to PORT\r\n");
- return n > 0 ? write(src, sbuf, n) : n;
- }
-
- memset(&data6, 0, sizeof(data6));
- sin = (struct sockaddr_in *)&data6;
- sin->sin_len = sizeof(*sin);
- sin->sin_family = AF_INET;
- sin->sin_addr.s_addr = htonl(
- ((ho[0] & 0xff) << 24) | ((ho[1] & 0xff) << 16) |
- ((ho[2] & 0xff) << 8) | (ho[3] & 0xff));
- sin->sin_port = htons(((po[0] & 0xff) << 8) | (po[1] & 0xff));
-
- /* get ready for active data connection */
- n = sizeof(data4);
- error = getsockname(dst, (struct sockaddr *)&data4, &n);
- if (error == -1) {
-portfail:
- n = snprintf(sbuf, sizeof(sbuf),
- "500 could not translate to EPRT\r\n");
- return n > 0 ? write(src, sbuf, n) : n;
- }
- if (((struct sockaddr *)&data4)->sa_family != AF_INET6)
- goto portfail;
-
- ((struct sockaddr_in6 *)&data4)->sin6_port = 0;
- sa = (struct sockaddr *)&data4;
- wport4 = socket(sa->sa_family, SOCK_STREAM, 0);
- if (wport4 == -1)
- goto portfail;
- error = bind(wport4, sa, sa->sa_len);
- if (error == -1) {
- close(wport4);
- wport4 = -1;
- goto portfail;
- }
- error = listen(wport4, 1);
- if (error == -1) {
- close(wport4);
- wport4 = -1;
- goto portfail;
- }
-
- /* transmit EPRT */
- n = sizeof(data4);
- error = getsockname(wport4, (struct sockaddr *)&data4, &n);
- if (error == -1) {
- close(wport4);
- wport4 = -1;
- goto portfail;
- }
- af = 2;
- sa = (struct sockaddr *)&data4;
- if (getnameinfo(sa, sa->sa_len, host, sizeof(host),
- serv, sizeof(serv), NI_NUMERICHOST | NI_NUMERICSERV)) {
- close(wport4);
- wport4 = -1;
- goto portfail;
- }
- n = snprintf(sbuf, sizeof(sbuf), "EPRT |%d|%s|%s|\r\n", af, host, serv);
- if (n > 0)
- n = write(dst, sbuf, n);
- *state = nstate;
- passivemode = 0;
- return n;
- } else if (strcmp(cmd, "PASV") == 0 && !param) {
- /*
- * PASV -> EPSV
- */
-
- nstate = PASV;
-
- close(wport4);
- close(wport6);
- close(port4);
- close(port6);
- wport4 = wport6 = port4 = port6 = -1;
-
- /* transmit EPSV */
- n = snprintf(sbuf, sizeof(sbuf), "EPSV\r\n");
- if (n > 0)
- n = write(dst, sbuf, n);
- *state = PASV;
- passivemode = 0; /* to be set to 1 later */
+ if (n < 0 || n >= sizeof(sbuf))
+ n = 0;
+ if (n)
+ write(src, sbuf, n);
return n;
-#else /* FAITH4 */
} else if (strcmp(cmd, "PORT") == 0 || strcmp(cmd, "PASV") == 0) {
/*
* reject PORT/PASV
*/
n = snprintf(sbuf, sizeof(sbuf), "502 %s not implemented.\r\n", cmd);
- return n > 0 ? write(src, sbuf, n) : n;
-#endif /* FAITH4 */
+ if (n < 0 || n >= sizeof(sbuf))
+ n = 0;
+ if (n)
+ write(src, sbuf, n);
+ return n;
} else if (passivemode
&& (strcmp(cmd, "STOR") == 0
|| strcmp(cmd, "STOU") == 0
@@ -1103,8 +1058,10 @@ portfail:
if (ftp_passiveconn() < 0) {
n = snprintf(sbuf, sizeof(sbuf), "425 Cannot open data connetion\r\n");
- if (n > 0)
- n = write(src, sbuf, n);
+ if (n < 0 || n >= sizeof(sbuf))
+ n = 0;
+ if (n)
+ write(src, sbuf, n);
} else {
/* simply relay the command */
write(dst, rbuf, n);
@@ -1115,7 +1072,8 @@ portfail:
} else {
/* simply relay it */
*state = NONE;
- return write(dst, rbuf, n);
+ write(dst, rbuf, n);
+ return n;
}
bad:
diff --git a/usr.sbin/faithd/prefix.c b/usr.sbin/faithd/prefix.c
index 45140ca..138c948 100644
--- a/usr.sbin/faithd/prefix.c
+++ b/usr.sbin/faithd/prefix.c
@@ -1,4 +1,4 @@
-/* $KAME: prefix.c,v 1.9 2001/07/02 14:36:49 itojun Exp $ */
+/* $KAME: prefix.c,v 1.13 2003/09/02 22:50:17 itojun Exp $ */
/* $FreeBSD$ */
/*
@@ -58,17 +58,16 @@ struct config *config_list = NULL;
const int niflags = NI_NUMERICHOST;
static int
-prefix_set(s, prefix, slash)
- const char *s;
- struct prefix *prefix;
- int slash;
+prefix_set(const char *s, struct prefix *prefix, int slash)
{
- char *p, *q, *r;
+ char *p = NULL, *q, *r;
struct addrinfo hints, *res = NULL;
int max;
char *a;
p = strdup(s);
+ if (!p)
+ goto fail;
q = strchr(p, '/');
if (q) {
if (!slash)
@@ -126,8 +125,7 @@ fail:
}
const char *
-prefix_string(prefix)
- const struct prefix *prefix;
+prefix_string(const struct prefix *prefix)
{
static char buf[NI_MAXHOST + 20];
char hbuf[NI_MAXHOST];
@@ -140,9 +138,7 @@ prefix_string(prefix)
}
int
-prefix_match(prefix, sa)
- const struct prefix *prefix;
- const struct sockaddr *sa;
+prefix_match(const struct prefix *prefix, const struct sockaddr *sa)
{
struct sockaddr_storage a, b;
char *pa, *pb;
@@ -194,8 +190,7 @@ prefix_match(prefix, sa)
* 3ffe::/16 permit 10.0.0.0/8 10.1.1.1
*/
static struct config *
-config_load1(line)
- const char *line;
+config_load1(const char *line)
{
struct config *conf;
char buf[BUFSIZ];
@@ -268,8 +263,7 @@ fail:
}
int
-config_load(configfile)
- const char *configfile;
+config_load(const char *configfile)
{
FILE *fp;
char buf[BUFSIZ];
@@ -285,6 +279,7 @@ config_load(configfile)
return -1;
p = &sentinel;
+ sentinel.next = NULL;
while (fgets(buf, sizeof(buf), fp) != NULL) {
conf = config_load1(buf);
if (conf) {
@@ -300,8 +295,7 @@ config_load(configfile)
#if 0
static void
-config_show1(conf)
- const struct config *conf;
+config_show1(const struct config *conf)
{
const char *p;
@@ -330,8 +324,7 @@ config_show()
#endif
const struct config *
-config_match(sa1, sa2)
- struct sockaddr *sa1, *sa2;
+config_match(struct sockaddr *sa1, struct sockaddr *sa2)
{
static struct config conf;
const struct config *p;
diff --git a/usr.sbin/faithd/rsh.c b/usr.sbin/faithd/rsh.c
deleted file mode 100644
index ab8e623e..0000000
--- a/usr.sbin/faithd/rsh.c
+++ /dev/null
@@ -1,212 +0,0 @@
-/* $KAME: rsh.c,v 1.7 2001/09/05 01:10:30 itojun Exp $ */
-
-/*
- * Copyright (C) 1997 and 1998 WIDE Project.
- * All rights reserved.
- *
- * 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. Neither the name of the project 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 PROJECT 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 PROJECT 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.
- *
- * $FreeBSD$
- */
-
-#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <sys/time.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <syslog.h>
-#include <unistd.h>
-#include <errno.h>
-
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-
-#include "faithd.h"
-
-char rshbuf[MSS];
-
-int s_ctl, s_ctl6, s_rcv, s_snd;
-int half;
-
-void
-rsh_relay(int s_src, int s_dst)
-{
- ssize_t n;
- fd_set readfds;
- int error;
- struct timeval tv;
-
- FD_ZERO(&readfds);
- FD_SET(s_src, &readfds);
- tv.tv_sec = FAITH_TIMEOUT;
- tv.tv_usec = 0;
- error = select(256, &readfds, NULL, NULL, &tv);
- if (error == -1)
- exit_failure("select %d: %s", s_src, strerror(errno));
- else if (error == 0)
- exit_failure("connection timeout");
-
- n = read(s_src, rshbuf, sizeof(rshbuf));
- if (rshbuf[0] != 0) {
- rsh_dual_relay(s_src, s_dst);
- /* NOTREACHED */
- }
- write(s_dst, rshbuf, n);
- tcp_relay(s_src, s_dst, "rsh");
- /* NOTREACHED */
-}
-
-static void
-relay(int src, int dst)
-{
- int error;
- ssize_t n;
- int atmark;
-
- error = ioctl(s_rcv, SIOCATMARK, &atmark);
- if (error != -1 && atmark == 1) {
- n = read(s_rcv, rshbuf, 1);
- if (n == 1)
- send(s_snd, rshbuf, 1, MSG_OOB);
- return;
- }
-
- n = read(s_rcv, rshbuf, sizeof(rshbuf));
-
- switch (n) {
- case -1:
- exit_failure("%s", strerror(errno));
- case 0:
- if (s_rcv == src) {
- /* half close */
- shutdown(dst, 1);
- half = YES;
- break;
- }
- close(src);
- close(dst);
- close(s_ctl);
- close(s_ctl6);
- exit_success("terminating rsh/contorol connections");
- break;
- default:
- write(s_snd, rshbuf, n);
- }
-}
-
-void
-rsh_dual_relay(int s_src, int s_dst)
-{
- fd_set readfds;
- int len, s_wld, error;
- struct sockaddr_storage ctladdr6;
- struct sockaddr_storage ctladdr;
- int port6 = 0, lport, lport6;
- char *p;
- struct timeval tv;
- struct sockaddr *sa;
-
- half = NO;
- s_rcv = s_src;
- s_snd = s_dst;
- syslog(LOG_INFO, "starting rsh connection");
-
- for (p = rshbuf; *p; p++)
- port6 = port6 * 10 + *p - '0';
-
- len = sizeof(ctladdr6);
- getpeername(s_src, (struct sockaddr *)&ctladdr6, &len);
- if (((struct sockaddr *)&ctladdr6)->sa_family == AF_INET6)
- ((struct sockaddr_in6 *)&ctladdr6)->sin6_port = htons(port6);
- else
- ((struct sockaddr_in *)&ctladdr6)->sin_port = htons(port6);
-
- s_wld = rresvport(&lport);
- if (s_wld == -1) goto bad;
- error = listen(s_wld, 1);
- if (error == -1) goto bad;
- snprintf(rshbuf, sizeof(rshbuf), "%d", lport);
- write(s_dst, rshbuf, strlen(rshbuf)+1);
-
- len = sizeof(ctladdr);
- s_ctl = accept(s_wld, (struct sockaddr *)&ctladdr, &len);
- if (s_ctl == -1) goto bad;
- close(s_wld);
-
- sa = (struct sockaddr *)&ctladdr6;
- s_ctl6 = rresvport_af(&lport6, sa->sa_family);
- if (s_ctl6 == -1) goto bad;
- error = connect(s_ctl6, sa, sa->sa_len);
- if (error == -1) goto bad;
-
- syslog(LOG_INFO, "starting rsh control connection");
-
- for (;;) {
- FD_ZERO(&readfds);
- if (half == NO)
- FD_SET(s_src, &readfds);
- FD_SET(s_dst, &readfds);
- FD_SET(s_ctl, &readfds);
- FD_SET(s_ctl6, &readfds);
- tv.tv_sec = FAITH_TIMEOUT;
- tv.tv_usec = 0;
-
- error = select(256, &readfds, NULL, NULL, &tv);
- if (error == -1)
- exit_failure("select 4 sockets: %s", strerror(errno));
- else if (error == 0)
- exit_failure("connection timeout");
-
- if (half == NO && FD_ISSET(s_src, &readfds)) {
- s_rcv = s_src;
- s_snd = s_dst;
- relay(s_src, s_dst);
- }
- if (FD_ISSET(s_dst, &readfds)) {
- s_rcv = s_dst;
- s_snd = s_src;
- relay(s_src, s_dst);
- }
- if (FD_ISSET(s_ctl, &readfds)) {
- s_rcv = s_ctl;
- s_snd = s_ctl6;
- relay(s_src, s_dst);
- }
- if (FD_ISSET(s_ctl6, &readfds)) {
- s_rcv = s_ctl6;
- s_snd = s_ctl;
- relay(s_src, s_dst);
- }
- }
- /* NOTREACHED */
-
- bad:
- exit_failure("%s", strerror(errno));
-}
diff --git a/usr.sbin/faithd/tcp.c b/usr.sbin/faithd/tcp.c
index 68a2f51..714df9a 100644
--- a/usr.sbin/faithd/tcp.c
+++ b/usr.sbin/faithd/tcp.c
@@ -1,4 +1,4 @@
-/* $KAME: tcp.c,v 1.8 2001/11/21 07:40:22 itojun Exp $ */
+/* $KAME: tcp.c,v 1.13 2003/09/02 22:49:21 itojun Exp $ */
/*
* Copyright (C) 1997 and 1998 WIDE Project.
@@ -93,8 +93,9 @@ sig_child(int sig)
pid_t pid;
pid = wait3(&status, WNOHANG, (struct rusage *)0);
- if (pid && WEXITSTATUS(status))
- syslog(LOG_WARNING, "child %d exit status 0x%x", pid, status);
+ if (pid > 0 && WEXITSTATUS(status))
+ syslog(LOG_WARNING, "child %ld exit status 0x%x",
+ (long)pid, status);
exit_success("terminate connection due to child termination");
}
@@ -156,6 +157,8 @@ send_data(int s_rcv, int s_snd, const char *service, int direction)
if (cc == -1)
goto retry_or_err;
oob_exists = 0;
+ if (s_rcv >= FD_SETSIZE)
+ exit_failure("descriptor too big");
FD_SET(s_rcv, &exceptfds);
}
@@ -174,12 +177,18 @@ send_data(int s_rcv, int s_snd, const char *service, int direction)
}
#endif /* DEBUG */
tblen = 0; tboff = 0;
+ if (s_snd >= FD_SETSIZE)
+ exit_failure("descriptor too big");
FD_CLR(s_snd, &writefds);
+ if (s_rcv >= FD_SETSIZE)
+ exit_failure("descriptor too big");
FD_SET(s_rcv, &readfds);
return;
retry_or_err:
if (errno != EAGAIN)
exit_failure("writing relay data failed: %s", strerror(errno));
+ if (s_snd >= FD_SETSIZE)
+ exit_failure("descriptor too big");
FD_SET(s_snd, &writefds);
}
@@ -195,6 +204,8 @@ relay(int s_rcv, int s_snd, const char *service, int direction)
FD_ZERO(&exceptfds);
fcntl(s_snd, F_SETFD, O_NONBLOCK);
oreadfds = readfds; owritefds = writefds; oexceptfds = exceptfds;
+ if (s_rcv >= FD_SETSIZE)
+ exit_failure("descriptor too big");
FD_SET(s_rcv, &readfds);
FD_SET(s_rcv, &exceptfds);
oob_exists = 0;
@@ -229,7 +240,11 @@ relay(int s_rcv, int s_snd, const char *service, int direction)
oob_read_retry:
cc = read(s_rcv, atmark_buf, 1);
if (cc == 1) {
+ if (s_rcv >= FD_SETSIZE)
+ exit_failure("descriptor too big");
FD_CLR(s_rcv, &exceptfds);
+ if (s_snd >= FD_SETSIZE)
+ exit_failure("descriptor too big");
FD_SET(s_snd, &writefds);
oob_exists = 1;
} else if (cc == -1) {
@@ -262,7 +277,11 @@ relay(int s_rcv, int s_snd, const char *service, int direction)
exit_success("terminating %s relay", service);
/* NOTREACHED */
default:
+ if (s_rcv >= FD_SETSIZE)
+ exit_failure("descriptor too big");
FD_CLR(s_rcv, &readfds);
+ if (s_snd >= FD_SETSIZE)
+ exit_failure("descriptor too big");
FD_SET(s_snd, &writefds);
break;
}
diff --git a/usr.sbin/faithd/test/faithd.rb b/usr.sbin/faithd/test/faithd.rb
index 683b504..682f540 100644
--- a/usr.sbin/faithd/test/faithd.rb
+++ b/usr.sbin/faithd/test/faithd.rb
@@ -3,7 +3,7 @@
# highly experimental (not working right at all) and very limited
# functionality.
#
-# $Id: faithd.rb,v 1.1.1.1 1999/08/08 23:29:31 itojun Exp $
+# $Id: faithd.rb,v 1.1.2.4 1999/05/10 17:06:30 itojun Exp $
# $FreeBSD$
require "socket"
OpenPOWER on IntegriCloud