diff options
author | sjg <sjg@FreeBSD.org> | 2014-11-19 07:11:29 +0000 |
---|---|---|
committer | sjg <sjg@FreeBSD.org> | 2014-11-19 07:11:29 +0000 |
commit | fe59e49369d427d5c1636a04fa7e9ac9cc6d519b (patch) | |
tree | 479b76a41b7cbe8d873c5d0c6097336495efe434 /usr.sbin | |
parent | e909cd6c36ba76e0e2cd9682e08cd94ce5fec8e1 (diff) | |
download | FreeBSD-src-fe59e49369d427d5c1636a04fa7e9ac9cc6d519b.zip FreeBSD-src-fe59e49369d427d5c1636a04fa7e9ac9cc6d519b.tar.gz |
Removed from head
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/faithd/Makefile | 25 | ||||
-rw-r--r-- | usr.sbin/faithd/Makefile.depend | 21 | ||||
-rw-r--r-- | usr.sbin/faithd/README | 148 | ||||
-rw-r--r-- | usr.sbin/faithd/faithd.8 | 404 | ||||
-rw-r--r-- | usr.sbin/faithd/faithd.c | 908 | ||||
-rw-r--r-- | usr.sbin/faithd/faithd.h | 70 | ||||
-rw-r--r-- | usr.sbin/faithd/ftp.c | 1085 | ||||
-rw-r--r-- | usr.sbin/faithd/prefix.c | 345 | ||||
-rw-r--r-- | usr.sbin/faithd/prefix.h | 52 | ||||
-rw-r--r-- | usr.sbin/faithd/tcp.c | 324 | ||||
-rw-r--r-- | usr.sbin/faithd/test/faithd.rb | 312 | ||||
-rw-r--r-- | usr.sbin/ftp-proxy/ftp-proxy/Makefile | 19 | ||||
-rw-r--r-- | usr.sbin/ftp-proxy/ftp-proxy/Makefile.depend | 21 | ||||
-rw-r--r-- | usr.sbin/ftp-proxy/libevent/Makefile | 27 | ||||
-rw-r--r-- | usr.sbin/ftp-proxy/libevent/Makefile.depend | 14 |
15 files changed, 0 insertions, 3775 deletions
diff --git a/usr.sbin/faithd/Makefile b/usr.sbin/faithd/Makefile deleted file mode 100644 index dec45b9..0000000 --- a/usr.sbin/faithd/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (c) 1996 WIDE Project. All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modifications, are permitted provided that the above copyright notice -# and this paragraph are duplicated in all such forms and that any -# documentation, advertising materials, and other materials related to -# such distribution and use acknowledge that the software was developed -# by the WIDE Project, Japan. The name of the Project may not be used to -# endorse or promote products derived from this software without -# specific prior written permission. THIS SOFTWARE IS PROVIDED ``AS IS'' -# AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT -# LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE. -# -# $FreeBSD$ - -PROG= faithd -MAN= faithd.8 -SRCS= faithd.c tcp.c ftp.c prefix.c - -CFLAGS+= -DHAVE_POLL_H - -WARNS?= 2 - -.include <bsd.prog.mk> diff --git a/usr.sbin/faithd/Makefile.depend b/usr.sbin/faithd/Makefile.depend deleted file mode 100644 index d9ecce6..0000000 --- a/usr.sbin/faithd/Makefile.depend +++ /dev/null @@ -1,21 +0,0 @@ -# Autogenerated - do NOT edit! - -DEP_RELDIR := ${_PARSEDIR:S,${SRCTOP}/,,} - -DIRDEPS = \ - gnu/lib/csu \ - gnu/lib/libgcc \ - include \ - include/arpa \ - include/xlocale \ - lib/${CSU_DIR} \ - lib/libc \ - lib/libcompiler_rt \ - lib/libutil \ - - -.include <dirdeps.mk> - -.if ${DEP_RELDIR} == ${_DEP_RELDIR} -# local dependencies - needed for -jN in clean tree -.endif diff --git a/usr.sbin/faithd/README b/usr.sbin/faithd/README deleted file mode 100644 index 6628bf6..0000000 --- a/usr.sbin/faithd/README +++ /dev/null @@ -1,148 +0,0 @@ -Configuring FAITH IPv6-to-IPv4 TCP relay - -Kazu Yamamoto and Jun-ichiro itojun Hagino -$KAME: README,v 1.10 2003/01/06 21:40:33 sumikawa Exp $ -$FreeBSD$ - - -Introduction -============ - -FAITH is an IPv6-to-IPv4 TCP relay. It performs tcp relay just as some of -firewall-oriented gateway does, but between IPv6 and IPv4 with address -translation. -TCP connections has to be made from IPv6 node to IPv4 node. FAITH will -not relay connections for the opposite direction. -To perform relays, FAITH daemon needs to be executed on a router between -your local IPv6 site and outside IPv4 network. The daemon needs to be -invoked per each TCP services (TCP port number). - - IPv4 node "dest" = 123.4.5.6 - | - [[[[ outside IPv4 ocean ]]]] - | - node that runs FAITH-daemon (usually a router) - | - ==+=====+===+==== IPv6, or IPv4/v6 network in your site ^ - | | | connection - clients IPv6 node "src" | - -You will have to allocate an IPv6 address prefix to map IPv4 addresses into. -The following description uses 3ffe:0501:ffff:0000:: as example. -Please use a prefix which belongs to your site. -FAITH will make it possible to make an IPv6 TCP connection From IPv6 node -"src", toward IPv4 node "dest", by specifying FAITH-mapped address -3ffe:0501:ffff:0000::123.4.5.6 -(which is, 3ffe:0501:ffff:0000:0000:0000:7b04:0506). -The address mapping can be performed by hand:-), by special nameserver on -the network, or by special resolver on the source node. - - -Setup -===== - -The following example assumes: -- You have assigned 3ffe:0501:ffff:0000:: as FAITH adderss prefix. -- You are willing to provide IPv6-to IPv4 TCP relay for telnet. - -<<On the translating router on which faithd runs>> - -(1) If you have IPv6 TCP server for the "telnet" service, i.e. telnetd via - inet6d, disable that daemon. Comment out the line from "inet6d.conf" - and send the HUP signal to "inet6d". - -(2) Execute sysctl as root to enable FAITH support in the kernel. - - # sysctl net.inet6.ip6.keepfaith=1 - -(3) Route packets toward FAITH prefix into "faith0" interface. - - # ifconfig faith0 up - # route add -inet6 3ffe:0501:ffff:0000:: -prefixlen 64 ::1 - # route change -inet6 3ffe:0501:ffff:0000:: -prefixlen 64 -ifp faith0 - -(4) Execute "faithd" by root as follows: - - # faithd telnet /usr/libexec/telnetd telnetd - - 1st argument is a service name you are willing to provide TCP relay. - (it can be specified either by number "23" or by string "telnet") - 2nd argument is a path name for local IPv6 TCP server. If there is a - connection toward the router itself, this program will be invoked. - 3rd and the following arguments are arguments for the local IPv6 TCP - server. (3rd argument is typically the program name without its path.) - - More examples: - - # faithd ftpd /usr/libexec/ftpd ftpd -l - # faithd sshd - -If inetd(8) on your platform have special support for faithd, it is possible -to setup faithd services via inetd(8). Consult manpage for details. - - -<<Routing>> - -(4) Make sure that packets whose destinations match the prefix can -reach from the IPv6 host to the translating router. - -<<On the IPv6 host>> - -There are two ways to translate IPv4 address to IPv6 address: - (a) Faked by DNS - (b) Faked by /etc/hosts. - -(5.a) Install "newbie" and set up FAITH mode. See kit/ports/newbie. - -(5.b) Add an entry into /etc/hosts so that you can resolve hostname into -faked IPv6 addrss. For example, add the following line for www.netbsd.org: - - 3ffe:0501:ffff:0000::140.160.140.252 www.netbsd.org - -<<On the translating router on which faithd runs.>> - -(6) To see if "faithd" works, watch "/var/log/daemon". Note: please -setup "/etc/syslog.conf" so that LOG_DAEMON messages are to be stored -in "/var/log/daemon". - - <e.g.> - daemon.* /var/log/daemon - - -Access control -============== - -Since faithd implements TCP relaying service, it is critical to implement -proper access control to cope with malicious use. Bad guy may try to -use your relay router to circumvent access controls, or may try to -abuse your network (like sending SPAMs from IPv4 address that belong to you). -Install IPv6 packet filter directives that would reject traffic from -unwanted source. If you are using inetd-based setup, you may be able to -use access control mechanisms in inetd. - - -Advanced configuration -====================== - -If you would like to restrict IPv4 destination for translation, you may -want to do the following: - - # route add -inet6 3ffe:0501:ffff:0000::123.0.0.0 -prefixlen 104 ::1 - # route change -inet6 3ffe:0501:ffff:0000::123.0.0.0 -prefixlen 104 \ - -ifp faith0 - -By this way, you can restrict IPv4 destination to 123.0.0.0/8. -You may also want to reject packets toward 3ffe:0501:ffff:0000::/64 which -is not in 3ffe:0501:ffff:0000::123.0.0.0/104. This will be left as excerside -for the reader. - -By doing this, you will be able to provide your IPv4 web server to outside -IPv6 customers, without risks of unwanted open relays. - - [[[[ IPv6 network outside ]]]] | - | | connection - node that runs FAITH-daemon (usually a router) v - | - ========+======== IPv4/v6 network in your site - | (123.0.0.0/8) - IPv4 web server diff --git a/usr.sbin/faithd/faithd.8 b/usr.sbin/faithd/faithd.8 deleted file mode 100644 index 93a835b..0000000 --- a/usr.sbin/faithd/faithd.8 +++ /dev/null @@ -1,404 +0,0 @@ -.\" $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. -.\" -.\" 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$ -.\" -.Dd August 2, 2011 -.Dt FAITHD 8 -.Os -.Sh NAME -.Nm faithd -.Nd FAITH IPv6/v4 translator daemon -.Sh SYNOPSIS -.Nm -.Op Fl dp -.Op Fl f Ar configfile -.Ar service -.Op Ar serverpath Op Ar serverargs -.Sh DESCRIPTION -The -.Nm -utility provides IPv6-to-IPv4 TCP relaying. -It can only be used on an IPv4/v6 dual stack router. -.Pp -When -.Nm -receives -.Tn TCPv6 -traffic, it will relay the -.Tn TCPv6 -traffic to -.Tn TCPv4 . -The destination for the relayed -.Tn TCPv4 -connection will be determined by the last 4 octets of the original -.Tn IPv6 -destination. -For example, if -.Li 3ffe:0501:4819:ffff:: -is reserved for -.Nm , -and the -.Tn TCPv6 -destination address is -.Li 3ffe:0501:4819:ffff::0a01:0101 , -the traffic will be relayed to IPv4 destination -.Li 10.1.1.1 . -.Pp -To use the -.Nm -translation service, -an IPv6 address prefix must be reserved for mapping IPv4 addresses into. -The kernel must be properly configured to route all the TCP connections -toward the reserved IPv6 address prefix into the -.Xr faith 4 -pseudo interface, using the -.Xr route 8 -command. -Also, -.Xr sysctl 8 -should be used to configure -.Dv net.inet6.ip6.keepfaith -to -.Dv 1 . -.Pp -The router must be configured to capture all the TCP traffic -for the reserved -.Tn IPv6 -address prefix, by using -.Xr route 8 -and -.Xr sysctl 8 -commands. -.Pp -The -.Nm -utility needs special name-to-address translation logic, so that -hostnames get resolved into the special -.Tn IPv6 -address prefix. -For small-scale installations, use -.Xr hosts 5 ; -For large-scale installations, it is useful to have -a DNS server with special address translation support. -An implementation called -.Nm totd -is available at -.Pa http://www.vermicelli.pasta.cs.uit.no/software/totd.html . -Make sure you do not propagate translated DNS records over to normal -DNS, as it can cause severe problems. -.Ss Daemon mode -When -.Nm -is invoked as a standalone program, -.Nm -will daemonize itself. -The -.Nm -utility will listen to -.Tn TCPv6 -port -.Ar service . -If -.Tn TCPv6 -traffic to port -.Ar service -is found, it relays the connection. -.Pp -Since -.Nm -listens to TCP port -.Ar service , -it is not possible to run local TCP daemons for port -.Ar service -on the router, using -.Xr inetd 8 -or other standard mechanisms. -By specifying -.Ar serverpath -to -.Nm , -you can run local daemons on the router. -The -.Nm -utility will invoke a local daemon at -.Ar serverpath -if the destination address is a local interface address, -and will perform translation to IPv4 TCP in other cases. -You can also specify -.Ar serverargs -for the arguments for the local daemon. -.Pp -The following options are available: -.Bl -tag -width indent -.It Fl d -Debugging information will be generated using -.Xr syslog 3 . -.It Fl f Ar configfile -Specify a configuration file for access control. -See below. -.It Fl p -Use privileged TCP port number as source port, -for IPv4 TCP connection toward final destination. -For relaying -.Xr ftp 1 , -this flag is not necessary as special program code is supplied. -.El -.Pp -The -.Nm -utility will relay both normal and out-of-band TCP data. -It is capable of emulating TCP half close as well. -The -.Nm -utility includes special support for protocols used by -.Xr ftp 1 . -When translating the FTP protocol, -.Nm -translates network level addresses in -.Li PORT/LPRT/EPRT -and -.Li PASV/LPSV/EPSV -commands. -.Pp -Inactive sessions will be disconnected in 30 minutes, -to prevent stale sessions from chewing up resources. -This may be inappropriate for some services -(should this be configurable?). -.Ss inetd mode -When -.Nm -is invoked via -.Xr inetd 8 , -.Nm -will handle connections passed from standard input. -If the connection endpoint is in the reserved IPv6 address prefix, -.Nm -will relay the connection. -Otherwise, -.Nm -will invoke a service-specific daemon like -.Xr telnetd 8 , -by using the command argument passed from -.Xr inetd 8 . -.Pp -The -.Nm -utility determines operation mode by the local TCP port number, -and enables special protocol handling whenever necessary/possible. -For example, if -.Nm -is invoked via -.Xr inetd 8 -on the FTP port, it will operate as an FTP relay. -.Pp -The operation mode requires special support for -.Nm -in -.Xr inetd 8 . -.Ss Access control -To prevent malicious access, -.Nm -implements simple address-based access control. -With -.Pa /etc/faithd.conf -(or -.Ar configfile -specified by -.Fl f ) , -.Nm -will avoid relaying unwanted traffic. -The -.Pa faithd.conf -configuration file contains directives of the following format: -.Bl -bullet -.It -.Ar src Ns / Ns Ar slen Cm deny Ar dst Ns / Ns Ar dlen -.Pp -If the source address of a query matches -.Ar src Ns / Ns Ar slen , -and the translated destination address matches -.Ar dst Ns / Ns Ar dlen , -deny the connection. -.It -.Ar src Ns / Ns Ar slen Cm permit Ar dst Ns / Ns Ar dlen -.Pp -If the source address of a query matches -.Ar src Ns / Ns Ar slen , -and the translated destination address matches -.Ar dst Ns / Ns Ar 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) -the traffic will be denied. -.Pp -With inetd mode, -traffic may be filtered by using access control functionality in -.Xr inetd 8 . -.Sh EXIT STATUS -The -.Nm -utility exits with -.Dv EXIT_SUCCESS -.Pq 0 -on success, and -.Dv EXIT_FAILURE -.Pq 1 -on error. -.Sh EXAMPLES -Before invoking -.Nm , -the -.Xr faith 4 -interface has to be configured properly. -.Bd -literal -offset indent -# sysctl net.inet6.ip6.accept_rtadv=0 -# sysctl net.inet6.ip6.forwarding=1 -# sysctl net.inet6.ip6.keepfaith=1 -# ifconfig faith0 up -# route add -inet6 3ffe:501:4819:ffff:: -prefixlen 96 ::1 -# route change -inet6 3ffe:501:4819:ffff:: -prefixlen 96 -ifp faith0 -.Ed -.Ss Daemon mode samples -To translate -.Li telnet -service, and provide no local telnet service, invoke -.Nm -as follows: -.Bd -literal -offset indent -# faithd telnet -.Ed -.Pp -If you would like to provide local telnet service via -.Xr telnetd 8 -on -.Pa /usr/libexec/telnetd , -use the following command line: -.Bd -literal -offset indent -# faithd telnet /usr/libexec/telnetd telnetd -.Ed -.Pp -If you would like to pass extra arguments to the local daemon: -.Bd -literal -offset indent -# faithd ftp /usr/libexec/ftpd ftpd -l -.Ed -.Pp -Here are some other examples. -You may need -.Fl p -if the service checks the source port range. -.Bd -literal -offset indent -# faithd ssh -# faithd telnet /usr/libexec/telnetd telnetd -.Ed -.Ss inetd mode samples -Add the following lines into -.Xr inetd.conf 5 . -Syntax may vary depending upon your operating system. -.Bd -literal -offset indent -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 -will open listening sockets with kernel TCP relay support enabled. -Whenever a connection comes in, -.Nm -will be invoked by -.Xr inetd 8 . -If the connection endpoint is in the reserved IPv6 address prefix. -The -.Nm -utility will relay the connection. -Otherwise, -.Nm -will invoke service-specific daemon like -.Xr telnetd 8 . -.Ss Access control samples -The following illustrates a simple -.Pa faithd.conf -setting. -.Bd -literal -offset indent -# permit anyone from 3ffe:501:ffff::/48 to use the translator, -# to connect to the following IPv4 destinations: -# - any location except 10.0.0.0/8 and 127.0.0.0/8. -# Permit no other connections. -# -3ffe:501:ffff::/48 deny 10.0.0.0/8 -3ffe:501:ffff::/48 deny 127.0.0.0/8 -3ffe:501:ffff::/48 permit 0.0.0.0/0 -.Ed -.Sh SEE ALSO -.Xr faith 4 , -.Xr route 8 , -.Xr sysctl 8 -.Rs -.%A Jun-ichiro itojun Hagino -.%A Kazu Yamamoto -.%T "An IPv6-to-IPv4 transport relay translator" -.%B RFC3142 -.%U http://tools.ietf.org/html/rfc3142 -.%D June 2001 -.Re -.\" -.Sh HISTORY -The -.Nm -utility first appeared in the WIDE Hydrangea IPv6 protocol stack kit. -.\" -.Pp -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 IP-address based authentication, for connections relayed by -.Nm , -and any other TCP relaying services. -.Pp -Administrators are advised to limit accesses to -.Nm -using -.Pa faithd.conf , -or by using IPv6 packet filters, to protect the -.Nm -service from malicious parties, and to avoid theft of service/bandwidth. -IPv6 destination addresses can be limited by -carefully configuring routing entries that point to -.Xr faith 4 , -using -.Xr route 8 . -The IPv6 source address needs to be filtered using packet filters. -The documents listed in -.Sx SEE ALSO -have more information on this topic. diff --git a/usr.sbin/faithd/faithd.c b/usr.sbin/faithd/faithd.c deleted file mode 100644 index 1745de1..0000000 --- a/usr.sbin/faithd/faithd.c +++ /dev/null @@ -1,908 +0,0 @@ -/* $KAME: faithd.c,v 1.67 2003/10/16 05:26:21 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. - */ - -/* - * User level translator from IPv6 to IPv4. - * - * Usage: faithd [<port> <progpath> <arg1(progname)> <arg2> ...] - * e.g. faithd telnet /usr/libexec/telnetd telnetd - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/types.h> -#include <sys/sysctl.h> -#include <sys/socket.h> -#include <sys/wait.h> -#include <sys/stat.h> -#include <sys/time.h> -#include <sys/ioctl.h> -#include <libutil.h> - -#ifdef HAVE_POLL_H -#include <poll.h> -#endif -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> -#include <string.h> -#include <syslog.h> -#include <unistd.h> -#include <errno.h> -#include <signal.h> -#include <fcntl.h> -#include <termios.h> - -#include <net/if_types.h> -#ifdef IFT_FAITH -# define USE_ROUTE -# include <net/if.h> -# include <net/route.h> -# include <net/if_dl.h> -#endif - -#include <netinet/in.h> -#include <arpa/inet.h> -#include <netdb.h> -#include <ifaddrs.h> - -#include "faithd.h" -#include "prefix.h" - -char *serverpath = NULL; -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; -#endif -int dflag = 0; -static int pflag = 0; -static int inetd = 0; -static char *configfile = NULL; - -int main(int, char **); -static int inetd_main(int, char **); -static int daemon_main(int, char **); -static void play_service(int); -static void play_child(int, struct sockaddr *); -static int faith_prefix(struct sockaddr *); -static int map6to4(struct sockaddr_in6 *, struct sockaddr_in *); -static void sig_child(int); -static void sig_terminate(int); -static void start_daemon(void); -static void exit_stderr(const char *, ...) - __attribute__((__format__(__printf__, 1, 2))); -static void grab_myaddrs(void); -static void free_myaddrs(void); -static void update_myaddrs(void); -static void usage(void); - -int -main(int argc, char **argv) -{ - - /* - * Initializing stuff - */ - - faithdname = strrchr(argv[0], '/'); - if (faithdname) - faithdname++; - else - faithdname = argv[0]; - - if (strcmp(faithdname, "faithd") != 0) { - inetd = 1; - return inetd_main(argc, argv); - } else - return daemon_main(argc, argv); -} - -static int -inetd_main(int argc, char **argv) -{ - char path[MAXPATHLEN]; - struct sockaddr_storage me; - struct sockaddr_storage from; - socklen_t melen, fromlen; - int i; - int error; - const int on = 1; - char sbuf[NI_MAXSERV], snum[NI_MAXSERV]; - - if (config_load(configfile) < 0 && configfile) { - exit_failure("could not load config file"); - /*NOTREACHED*/ - } - - if (strrchr(argv[0], '/') == NULL) - snprintf(path, sizeof(path), "%s/%s", DEFAULT_DIR, argv[0]); - else - snprintf(path, sizeof(path), "%s", argv[0]); - -#ifdef USE_ROUTE - grab_myaddrs(); - - sockfd = socket(PF_ROUTE, SOCK_RAW, PF_UNSPEC); - if (sockfd < 0) { - exit_failure("socket(PF_ROUTE): %s", strerror(errno)); - /*NOTREACHED*/ - } -#endif - - melen = sizeof(me); - if (getsockname(STDIN_FILENO, (struct sockaddr *)&me, &melen) < 0) { - exit_failure("getsockname: %s", strerror(errno)); - /*NOTREACHED*/ - } - fromlen = sizeof(from); - if (getpeername(STDIN_FILENO, (struct sockaddr *)&from, &fromlen) < 0) { - exit_failure("getpeername: %s", strerror(errno)); - /*NOTREACHED*/ - } - if (getnameinfo((struct sockaddr *)&me, melen, NULL, 0, - sbuf, sizeof(sbuf), NI_NUMERICHOST) == 0) - service = sbuf; - else - service = DEFAULT_PORT_NAME; - if (getnameinfo((struct sockaddr *)&me, melen, NULL, 0, - snum, sizeof(snum), NI_NUMERICHOST) != 0) - snprintf(snum, sizeof(snum), "?"); - - snprintf(logname, sizeof(logname), "faithd %s", snum); - snprintf(procname, sizeof(procname), "accepting port %s", snum); - openlog(logname, LOG_PID | LOG_NOWAIT, LOG_DAEMON); - - if (argc >= MAXARGV) { - exit_failure("too many arguments"); - /*NOTREACHED*/ - } - serverarg[0] = serverpath = path; - for (i = 1; i < argc; i++) - serverarg[i] = argv[i]; - serverarg[i] = NULL; - - error = setsockopt(STDIN_FILENO, SOL_SOCKET, SO_OOBINLINE, &on, - sizeof(on)); - if (error < 0) { - exit_failure("setsockopt(SO_OOBINLINE): %s", strerror(errno)); - /*NOTREACHED*/ - } - - play_child(STDIN_FILENO, (struct sockaddr *)&from); - exit_failure("should not reach here"); - return 0; /*dummy!*/ -} - -static int -daemon_main(int argc, char **argv) -{ - struct addrinfo hints, *res; - int s_wld, error, i, serverargc, on = 1; - int family = AF_INET6; - int c; - - while ((c = getopt(argc, argv, "df:p")) != -1) { - switch (c) { - case 'd': - dflag++; - break; - case 'f': - configfile = optarg; - break; - case 'p': - pflag++; - break; - default: - usage(); - /*NOTREACHED*/ - } - } - argc -= optind; - argv += optind; - - if (config_load(configfile) < 0 && configfile) { - exit_failure("could not load config file"); - /*NOTREACHED*/ - } - - -#ifdef USE_ROUTE - grab_myaddrs(); -#endif - - switch (argc) { - case 0: - usage(); - /*NOTREACHED*/ - default: - serverargc = argc - NUMARG; - if (serverargc >= MAXARGV) - exit_stderr("too many arguments"); - - serverpath = strdup(argv[NUMPRG]); - if (!serverpath) - exit_stderr("not enough core"); - for (i = 0; i < serverargc; i++) { - serverarg[i] = strdup(argv[i + NUMARG]); - if (!serverarg[i]) - exit_stderr("not enough core"); - } - serverarg[i] = NULL; - /* fall throuth */ - case 1: /* no local service */ - service = argv[NUMPRT]; - break; - } - - start_daemon(); - - /* - * Opening wild card socket for this service. - */ - - memset(&hints, 0, sizeof(hints)); - hints.ai_flags = AI_PASSIVE; - hints.ai_family = family; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; /* SCTP? */ - error = getaddrinfo(NULL, service, &hints, &res); - if (error) - exit_failure("getaddrinfo: %s", gai_strerror(error)); - - s_wld = socket(res->ai_family, res->ai_socktype, res->ai_protocol); - if (s_wld == -1) - exit_failure("socket: %s", strerror(errno)); - -#ifdef IPV6_FAITH - if (res->ai_family == AF_INET6) { - error = setsockopt(s_wld, IPPROTO_IPV6, IPV6_FAITH, &on, sizeof(on)); - if (error == -1) - exit_failure("setsockopt(IPV6_FAITH): %s", - strerror(errno)); - } -#endif - - error = setsockopt(s_wld, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); - if (error == -1) - exit_failure("setsockopt(SO_REUSEADDR): %s", strerror(errno)); - - error = setsockopt(s_wld, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on)); - 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)); - - error = listen(s_wld, 5); - if (error == -1) - exit_failure("listen: %s", strerror(errno)); - -#ifdef USE_ROUTE - sockfd = socket(PF_ROUTE, SOCK_RAW, PF_UNSPEC); - if (sockfd < 0) { - exit_failure("socket(PF_ROUTE): %s", strerror(errno)); - /*NOTREACHED*/ - } -#endif - - /* - * Everything is OK. - */ - - snprintf(logname, sizeof(logname), "faithd %s", service); - snprintf(procname, sizeof(procname), "accepting port %s", service); - openlog(logname, LOG_PID | LOG_NOWAIT, LOG_DAEMON); - syslog(LOG_INFO, "Starting faith daemon for %s port", service); - - play_service(s_wld); - /* NOTREACHED */ - exit(1); /*pacify gcc*/ -} - -static void -play_service(int s_wld) -{ - struct sockaddr_storage srcaddr; - socklen_t len; - int s_src; - pid_t child_pid; -#ifdef HAVE_POLL_H - struct pollfd pfd[2]; -#else - fd_set rfds; - int maxfd; -#endif - int error; - - /* - * Wait, accept, fork, faith.... - */ -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; - exit_failure("select: %s", strerror(errno)); - /*NOTREACHED*/ - } - -#ifdef USE_ROUTE -#ifdef HAVE_POLL_H - if (pfd[1].revents & POLLIN) -#else - if (FD_ISSET(sockfd, &rfds)) -#endif - { - update_myaddrs(); - } -#endif -#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); - 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); - closelog(); - openlog(logname, LOG_PID | LOG_NOWAIT, LOG_DAEMON); - play_child(s_src, (struct sockaddr *)&srcaddr); - exit_failure("should never reach here"); - /*NOTREACHED*/ - } else { - /* parent process */ - close(s_src); - if (child_pid == -1) - syslog(LOG_ERR, "can't fork"); - } - } - goto again; -} - -static void -play_child(int s_src, struct sockaddr *srcaddr) -{ - struct sockaddr_storage dstaddr6; - struct sockaddr_storage dstaddr4; - char src[NI_MAXHOST]; - char dst6[NI_MAXHOST]; - char dst4[NI_MAXHOST]; - socklen_t len = sizeof(dstaddr6); - int s_dst, error, hport, nresvport, on = 1; - struct timeval tv; - struct sockaddr *sa4; - const struct config *conf; - - tv.tv_sec = 1; - tv.tv_usec = 0; - - getnameinfo(srcaddr, srcaddr->sa_len, - src, sizeof(src), NULL, 0, NI_NUMERICHOST); - syslog(LOG_INFO, "accepted a client from %s", src); - - error = getsockname(s_src, (struct sockaddr *)&dstaddr6, &len); - if (error == -1) { - exit_failure("getsockname: %s", strerror(errno)); - /*NOTREACHED*/ - } - - getnameinfo((struct sockaddr *)&dstaddr6, len, - dst6, sizeof(dst6), NULL, 0, NI_NUMERICHOST); - syslog(LOG_INFO, "the client is connecting to %s", dst6); - - if (!faith_prefix((struct sockaddr *)&dstaddr6)) { - if (serverpath) { - /* - * Local service - */ - syslog(LOG_INFO, "executing local %s", serverpath); - if (!inetd) { - dup2(s_src, 0); - close(s_src); - dup2(0, 1); - dup2(0, 2); - } - execv(serverpath, serverarg); - syslog(LOG_ERR, "execv %s: %s", serverpath, - strerror(errno)); - _exit(EXIT_FAILURE); - } else { - close(s_src); - exit_success("no local service for %s", service); - } - } - - /* - * Act as a translator - */ - - switch (((struct sockaddr *)&dstaddr6)->sa_family) { - case AF_INET6: - if (!map6to4((struct sockaddr_in6 *)&dstaddr6, - (struct sockaddr_in *)&dstaddr4)) { - close(s_src); - exit_failure("map6to4 failed"); - /*NOTREACHED*/ - } - syslog(LOG_INFO, "translating from v6 to v4"); - break; - default: - close(s_src); - exit_failure("family not supported"); - /*NOTREACHED*/ - } - - sa4 = (struct sockaddr *)&dstaddr4; - getnameinfo(sa4, sa4->sa_len, - dst4, sizeof(dst4), NULL, 0, NI_NUMERICHOST); - - conf = config_match(srcaddr, sa4); - if (!conf || !conf->permit) { - close(s_src); - if (conf) { - exit_failure("translation to %s not permitted for %s", - dst4, prefix_string(&conf->match)); - /*NOTREACHED*/ - } else { - exit_failure("translation to %s not permitted", dst4); - /*NOTREACHED*/ - } - } - - syslog(LOG_INFO, "the translator is connecting to %s", dst4); - - setproctitle("port %s, %s -> %s", service, src, dst4); - - if (sa4->sa_family == AF_INET6) - hport = ntohs(((struct sockaddr_in6 *)&dstaddr4)->sin6_port); - else /* AF_INET */ - hport = ntohs(((struct sockaddr_in *)&dstaddr4)->sin_port); - - if (pflag) - s_dst = rresvport_af(&nresvport, sa4->sa_family); - else - s_dst = socket(sa4->sa_family, SOCK_STREAM, 0); - if (s_dst < 0) { - exit_failure("socket: %s", strerror(errno)); - /*NOTREACHED*/ - } - - if (conf->src.a.ss_family) { - if (bind(s_dst, (const struct sockaddr *)&conf->src.a, - conf->src.a.ss_len) < 0) { - exit_failure("bind: %s", strerror(errno)); - /*NOTREACHED*/ - } - } - - error = setsockopt(s_dst, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on)); - if (error < 0) { - exit_failure("setsockopt(SO_OOBINLINE): %s", strerror(errno)); - /*NOTREACHED*/ - } - - error = setsockopt(s_src, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); - if (error < 0) { - exit_failure("setsockopt(SO_SNDTIMEO): %s", strerror(errno)); - /*NOTREACHED*/ - } - error = setsockopt(s_dst, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); - if (error < 0) { - exit_failure("setsockopt(SO_SNDTIMEO): %s", strerror(errno)); - /*NOTREACHED*/ - } - - error = connect(s_dst, sa4, sa4->sa_len); - if (error < 0) { - exit_failure("connect: %s", strerror(errno)); - /*NOTREACHED*/ - } - - switch (hport) { - case FTP_PORT: - ftp_relay(s_src, s_dst); - break; - default: - tcp_relay(s_src, s_dst, service); - break; - } - - /* NOTREACHED */ -} - -/* 0: non faith, 1: faith */ -static int -faith_prefix(struct sockaddr *dst) -{ -#ifndef USE_ROUTE - int mib[4], size; - struct in6_addr faith_prefix; - struct sockaddr_in6 *dst6 = (struct sockaddr_in *)dst; - - if (dst->sa_family != AF_INET6) - return 0; - - mib[0] = CTL_NET; - mib[1] = PF_INET6; - mib[2] = IPPROTO_IPV6; - mib[3] = IPV6CTL_FAITH_PREFIX; - size = sizeof(struct in6_addr); - if (sysctl(mib, 4, &faith_prefix, &size, NULL, 0) < 0) { - exit_failure("sysctl: %s", strerror(errno)); - /*NOTREACHED*/ - } - - if (memcmp(dst, &faith_prefix, - sizeof(struct in6_addr) - sizeof(struct in_addr) == 0) { - return 1; - } - return 0; -#else - struct myaddrs *p; - struct sockaddr_in6 *sin6; - struct sockaddr_in *sin4; - struct sockaddr_in6 *dst6; - struct sockaddr_in *dst4; - struct sockaddr_in dstmap; - - dst6 = (struct sockaddr_in6 *)dst; - if (dst->sa_family == AF_INET6 - && IN6_IS_ADDR_V4MAPPED(&dst6->sin6_addr)) { - /* ugly... */ - memset(&dstmap, 0, sizeof(dstmap)); - dstmap.sin_family = AF_INET; - dstmap.sin_len = sizeof(dstmap); - memcpy(&dstmap.sin_addr, &dst6->sin6_addr.s6_addr[12], - sizeof(dstmap.sin_addr)); - dst = (struct sockaddr *)&dstmap; - } - - dst6 = (struct sockaddr_in6 *)dst; - dst4 = (struct sockaddr_in *)dst; - - for (p = myaddrs; p; p = p->next) { - sin6 = (struct sockaddr_in6 *)p->addr; - sin4 = (struct sockaddr_in *)p->addr; - - if (p->addr->sa_len != dst->sa_len - || p->addr->sa_family != dst->sa_family) - continue; - - switch (dst->sa_family) { - case AF_INET6: - if (sin6->sin6_scope_id == dst6->sin6_scope_id - && IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &dst6->sin6_addr)) - return 0; - break; - case AF_INET: - if (sin4->sin_addr.s_addr == dst4->sin_addr.s_addr) - return 0; - break; - } - } - return 1; -#endif -} - -/* 0: non faith, 1: faith */ -static int -map6to4(struct sockaddr_in6 *dst6, struct sockaddr_in *dst4) -{ - memset(dst4, 0, sizeof(*dst4)); - dst4->sin_len = sizeof(*dst4); - dst4->sin_family = AF_INET; - dst4->sin_port = dst6->sin6_port; - memcpy(&dst4->sin_addr, &dst6->sin6_addr.s6_addr[12], - sizeof(dst4->sin_addr)); - - if (dst4->sin_addr.s_addr == INADDR_ANY - || dst4->sin_addr.s_addr == INADDR_BROADCAST - || IN_MULTICAST(ntohl(dst4->sin_addr.s_addr))) - return 0; - - return 1; -} - - -static void -sig_child(int sig __unused) -{ - int status; - pid_t pid; - - 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 -sig_terminate(int sig __unused) -{ - syslog(LOG_INFO, "Terminating faith daemon"); - exit(EXIT_SUCCESS); -} - -static void -start_daemon(void) -{ -#ifdef SA_NOCLDWAIT - struct sigaction sa; -#endif - - if (daemon(0, 0) == -1) - exit_stderr("daemon: %s", strerror(errno)); - -#ifdef SA_NOCLDWAIT - memset(&sa, 0, sizeof(sa)); - sa.sa_handler = sig_child; - sa.sa_flags = SA_NOCLDWAIT; - sigemptyset(&sa.sa_mask); - sigaction(SIGCHLD, &sa, (struct sigaction *)0); -#else - if (signal(SIGCHLD, sig_child) == SIG_ERR) { - exit_failure("signal CHLD: %s", strerror(errno)); - /*NOTREACHED*/ - } -#endif - - if (signal(SIGTERM, sig_terminate) == SIG_ERR) { - exit_failure("signal TERM: %s", strerror(errno)); - /*NOTREACHED*/ - } -} - -static void -exit_stderr(const char *fmt, ...) -{ - va_list ap; - char buf[BUFSIZ]; - - va_start(ap, fmt); - vsnprintf(buf, sizeof(buf), fmt, ap); - va_end(ap); - fprintf(stderr, "%s\n", buf); - exit(EXIT_FAILURE); -} - -void -exit_failure(const char *fmt, ...) -{ - va_list ap; - char buf[BUFSIZ]; - - va_start(ap, fmt); - vsnprintf(buf, sizeof(buf), fmt, ap); - va_end(ap); - syslog(LOG_ERR, "%s", buf); - exit(EXIT_FAILURE); -} - -void -exit_success(const char *fmt, ...) -{ - va_list ap; - char buf[BUFSIZ]; - - va_start(ap, fmt); - vsnprintf(buf, sizeof(buf), fmt, ap); - va_end(ap); - syslog(LOG_INFO, "%s", buf); - exit(EXIT_SUCCESS); -} - -#ifdef USE_ROUTE -static void -grab_myaddrs(void) -{ - struct ifaddrs *ifap, *ifa; - struct myaddrs *p; - struct sockaddr_in6 *sin6; - - if (getifaddrs(&ifap) != 0) { - exit_failure("getifaddrs"); - /*NOTREACHED*/ - } - - for (ifa = ifap; ifa; ifa = ifa->ifa_next) { - switch (ifa->ifa_addr->sa_family) { - case AF_INET: - case AF_INET6: - break; - default: - continue; - } - - p = (struct myaddrs *)malloc(sizeof(struct myaddrs) + - ifa->ifa_addr->sa_len); - if (!p) { - exit_failure("not enough core"); - /*NOTREACHED*/ - } - memcpy(p + 1, ifa->ifa_addr, ifa->ifa_addr->sa_len); - p->next = myaddrs; - p->addr = (struct sockaddr *)(p + 1); -#ifdef __KAME__ - if (ifa->ifa_addr->sa_family == AF_INET6) { - sin6 = (struct sockaddr_in6 *)p->addr; - if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) - || IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) { - sin6->sin6_scope_id = - ntohs(*(u_int16_t *)&sin6->sin6_addr.s6_addr[2]); - sin6->sin6_addr.s6_addr[2] = 0; - sin6->sin6_addr.s6_addr[3] = 0; - } - } -#endif - myaddrs = p; - if (dflag) { - char hbuf[NI_MAXHOST]; - getnameinfo(p->addr, p->addr->sa_len, - hbuf, sizeof(hbuf), NULL, 0, - NI_NUMERICHOST); - syslog(LOG_INFO, "my interface: %s %s", hbuf, - ifa->ifa_name); - } - } - - freeifaddrs(ifap); -} - -static void -free_myaddrs(void) -{ - struct myaddrs *p, *q; - - p = myaddrs; - while (p) { - q = p->next; - free(p); - p = q; - } - myaddrs = NULL; -} - -static void -update_myaddrs(void) -{ - char msg[BUFSIZ]; - int len; - struct rt_msghdr *rtm; - - len = read(sockfd, msg, sizeof(msg)); - if (len < 0) { - syslog(LOG_ERR, "read(PF_ROUTE) failed"); - return; - } - rtm = (struct rt_msghdr *)msg; - if (len < 4 || len < rtm->rtm_msglen) { - syslog(LOG_ERR, "read(PF_ROUTE) short read"); - return; - } - if (rtm->rtm_version != RTM_VERSION) { - syslog(LOG_ERR, "routing socket version mismatch"); - close(sockfd); - sockfd = 0; - return; - } - switch (rtm->rtm_type) { - case RTM_NEWADDR: - case RTM_DELADDR: - case RTM_IFINFO: - break; - default: - return; - } - /* XXX more filters here? */ - - syslog(LOG_INFO, "update interface address list"); - free_myaddrs(); - grab_myaddrs(); -} -#endif /*USE_ROUTE*/ - -static void -usage(void) -{ - fprintf(stderr, "usage: %s [-dp] [-f conf] service [serverpath [serverargs]]\n", - faithdname); - exit(0); -} diff --git a/usr.sbin/faithd/faithd.h b/usr.sbin/faithd/faithd.h deleted file mode 100644 index c578d46..0000000 --- a/usr.sbin/faithd/faithd.h +++ /dev/null @@ -1,70 +0,0 @@ -/* $KAME: faithd.h,v 1.9 2002/05/09 09:41:24 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$ - */ - -extern char logname[]; -extern int dflag; - -extern void tcp_relay(int, int, const char *); -extern void ftp_relay(int, int); -extern int ftp_active(int, int, int *, int *); -extern int ftp_passive(int, int, int *, int *); -extern void exit_success(const char *, ...) - __attribute__((__format__(__printf__, 1, 2))); -extern void exit_failure(const char *, ...) - __attribute__((__format__(__printf__, 1, 2))); - -#define DEFAULT_PORT_NAME "telnet" -#define DEFAULT_DIR "/usr/libexec" -#define DEFAULT_NAME "telnetd" -#define DEFAULT_PATH (DEFAULT_DIR "/" DEFAULT_NAME) - -#define FTP_PORT 21 -#define RLOGIN_PORT 513 -#define RSH_PORT 514 - -#define RETURN_SUCCESS 0 -#define RETURN_FAILURE 1 - -#define YES 1 -#define NO 0 - -#define MSS 2048 -#define MAXARGV 20 - -#define NUMPRT 0 -#define NUMPRG 1 -#define NUMARG 2 - -#define UC(b) (((int)b)&0xff) - -#define FAITH_TIMEOUT (30 * 60) /*second*/ diff --git a/usr.sbin/faithd/ftp.c b/usr.sbin/faithd/ftp.c deleted file mode 100644 index c54371a..0000000 --- a/usr.sbin/faithd/ftp.c +++ /dev/null @@ -1,1085 +0,0 @@ -/* $KAME: ftp.c,v 1.24 2005/03/16 05:05:48 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> -#ifdef HAVE_POLL_H -#include <poll.h> -#endif -#include <errno.h> -#include <ctype.h> - -#include <netinet/in.h> -#include <arpa/inet.h> -#include <netdb.h> - -#include "faithd.h" - -static char rbuf[MSS]; -static char sbuf[MSS]; -static int passivemode = 0; -static int wport4 = -1; /* listen() to active */ -static int wport6 = -1; /* listen() to passive */ -static int port4 = -1; /* active: inbound passive: outbound */ -static int port6 = -1; /* active: outbound passive: inbound */ -static struct sockaddr_storage data4; /* server data address */ -static struct sockaddr_storage data6; /* client data address */ -static int epsvall = 0; - -enum state { NONE, LPRT, EPRT, LPSV, EPSV }; - -static int ftp_activeconn(void); -static int ftp_passiveconn(void); -static int ftp_copy(int, int); -static int ftp_copyresult(int, int, enum state); -static int ftp_copycommand(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; - - 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); - maxfd = (ctl6 > maxfd) ? ctl6 : maxfd; - if (0 <= port4) { - if (port4 >= FD_SETSIZE) - exit_failure("descriptor too big"); - FD_SET(port4, &readfds); - 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 (wport4 >= FD_SETSIZE) - exit_failure("descriptor too big"); - FD_SET(wport4, &readfds); - 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; - -#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"); - - /* - * The order of the following checks does (slightly) matter. - * It is important to visit all checks (do not use "continue"), - * otherwise some of the pipe may become full and we cannot - * relay correctly. - */ -#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. - */ - error = ftp_copycommand(ctl6, ctl4, &state); - - if (error < 0) - goto bad; - else if (error == 0) { - close(ctl4); - close(ctl6); - exit_success("terminating ftp control connection"); - /*NOTREACHED*/ - } - } -#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. - */ - error = ftp_copyresult(ctl4, ctl6, state); - - if (error < 0) - goto bad; - else if (error == 0) { - close(ctl4); - close(ctl6); - exit_success("terminating ftp control connection"); - /*NOTREACHED*/ - } - } -#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: - goto bad; - case 0: - close(port4); - close(port6); - port4 = port6 = -1; - syslog(LOG_INFO, "terminating data connection"); - break; - default: - break; - } - } -#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: - goto bad; - case 0: - close(port4); - close(port6); - port4 = port6 = -1; - syslog(LOG_INFO, "terminating data connection"); - break; - default: - break; - } - } -#if 0 -#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(); - } -#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. - */ - ftp_passiveconn(); - } -#endif - } - - bad: - exit_failure("%s", strerror(errno)); -} - -static int -ftp_activeconn() -{ - 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 = 0; - n = sizeof(data4); -#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"); - return -1; - } - - /* ask active connection to client */ - sa = (struct sockaddr *)&data6; - port6 = socket(sa->sa_family, SOCK_STREAM, 0); - if (port6 == -1) { - close(port4); - close(wport4); - port4 = wport4 = -1; - syslog(LOG_INFO, "active mode data connection failed"); - return -1; - } - error = connect(port6, sa, sa->sa_len); - if (error < 0) { - close(port6); - close(port4); - close(wport4); - port6 = port4 = wport4 = -1; - syslog(LOG_INFO, "active mode data connection failed"); - return -1; - } - - syslog(LOG_INFO, "active mode data connection established"); - return 0; -} - -static int -ftp_passiveconn() -{ - 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; - 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"); - return -1; - } - - /* ask passive connection to server */ - sa = (struct sockaddr *)&data4; - port4 = socket(sa->sa_family, SOCK_STREAM, 0); - if (port4 == -1) { - close(wport6); - close(port6); - wport6 = port6 = -1; - syslog(LOG_INFO, "passive mode data connection failed"); - return -1; - } - error = connect(port4, sa, sa->sa_len); - if (error < 0) { - close(wport6); - close(port4); - close(port6); - wport6 = port4 = port6 = -1; - syslog(LOG_INFO, "passive mode data connection failed"); - return -1; - } - - syslog(LOG_INFO, "passive mode data connection established"); - return 0; -} - -static int -ftp_copy(int src, int dst) -{ - int error, atmark, n; - - /* OOB data handling */ - error = ioctl(src, SIOCATMARK, &atmark); - if (error != -1 && atmark == 1) { - n = read(src, rbuf, 1); - if (n == -1) - goto bad; - send(dst, rbuf, n, MSG_OOB); -#if 0 - n = read(src, rbuf, sizeof(rbuf)); - if (n == -1) - goto bad; - write(dst, rbuf, n); - return n; -#endif - } - - n = read(src, rbuf, sizeof(rbuf)); - switch (n) { - case -1: - case 0: - return n; - default: - write(dst, rbuf, n); - return n; - } - - bad: - exit_failure("%s", strerror(errno)); - /*NOTREACHED*/ - return 0; /* to make gcc happy */ -} - -static int -ftp_copyresult(int src, int dst, enum state state) -{ - int error, atmark, n; - socklen_t len; - char *param; - int code; - char *a, *p; - int i; - - /* OOB data handling */ - error = ioctl(src, SIOCATMARK, &atmark); - if (error != -1 && atmark == 1) { - n = read(src, rbuf, 1); - if (n == -1) - goto bad; - send(dst, rbuf, n, MSG_OOB); -#if 0 - n = read(src, rbuf, sizeof(rbuf)); - if (n == -1) - goto bad; - write(dst, rbuf, n); - return n; -#endif - } - - n = read(src, rbuf, sizeof(rbuf)); - if (n <= 0) - return n; - rbuf[n] = '\0'; - - /* - * parse argument - */ - p = rbuf; - for (i = 0; i < 3; i++) { - if (!isdigit(*p)) { - /* invalid reply */ - write(dst, rbuf, n); - return n; - } - p++; - } - if (!isspace(*p)) { - /* invalid reply */ - write(dst, rbuf, n); - return n; - } - code = atoi(rbuf); - param = p; - /* param points to first non-command token, if any */ - while (*param && isspace(*param)) - param++; - if (!*param) - param = NULL; - - switch (state) { - case NONE: - if (!passivemode && rbuf[0] == '1') { - if (ftp_activeconn() < 0) { - n = snprintf(rbuf, sizeof(rbuf), - "425 Cannot open data connetion\r\n"); - if (n < 0 || n >= sizeof(rbuf)) - n = 0; - } - } - if (n) - write(dst, rbuf, n); - return n; - case LPRT: - case EPRT: - /* expecting "200 PORT command successful." */ - if (code == 200) { - p = strstr(rbuf, "PORT"); - if (p) { - p[0] = (state == LPRT) ? 'L' : 'E'; - p[1] = 'P'; - } - } else { - close(wport4); - wport4 = -1; - } - write(dst, rbuf, n); - return n; - case LPSV: - case EPSV: - /* - * expecting "227 Entering Passive Mode (x,x,x,x,x,x,x)" - * (in some cases result comes without paren) - */ - if (code != 227) { -passivefail0: - close(wport6); - wport6 = -1; - write(dst, rbuf, n); - return n; - } - - { - unsigned int ho[4], po[2]; - struct sockaddr_in *sin; - struct sockaddr_in6 *sin6; - u_short port; - - /* - * PASV result -> LPSV/EPSV result - */ - p = param; - while (*p && *p != '(' && !isdigit(*p)) /*)*/ - p++; - if (!*p) - goto passivefail0; /*XXX*/ - if (*p == '(') /*)*/ - p++; - n = sscanf(p, "%u,%u,%u,%u,%u,%u", - &ho[0], &ho[1], &ho[2], &ho[3], &po[0], &po[1]); - if (n != 6) - goto passivefail0; /*XXX*/ - - /* keep PORT parameter */ - memset(&data4, 0, sizeof(data4)); - sin = (struct sockaddr_in *)&data4; - sin->sin_len = sizeof(*sin); - sin->sin_family = AF_INET; - sin->sin_addr.s_addr = 0; - for (n = 0; n < 4; n++) { - sin->sin_addr.s_addr |= - htonl((ho[n] & 0xff) << ((3 - n) * 8)); - } - sin->sin_port = htons(((po[0] & 0xff) << 8) | (po[1] & 0xff)); - - /* get ready for passive data connection */ - memset(&data6, 0, sizeof(data6)); - sin6 = (struct sockaddr_in6 *)&data6; - sin6->sin6_len = sizeof(*sin6); - sin6->sin6_family = AF_INET6; - wport6 = socket(sin6->sin6_family, SOCK_STREAM, 0); - if (wport6 == -1) { -passivefail: - n = snprintf(sbuf, sizeof(sbuf), - "500 could not translate from PASV\r\n"); - if (n < 0 || n >= sizeof(sbuf)) - n = 0; - if (n) - write(src, sbuf, n); - return n; - } -#ifdef IPV6_FAITH - { - int on = 1; - error = setsockopt(wport6, IPPROTO_IPV6, IPV6_FAITH, - &on, sizeof(on)); - if (error == -1) - exit_failure("setsockopt(IPV6_FAITH): %s", strerror(errno)); - } -#endif - error = bind(wport6, (struct sockaddr *)sin6, sin6->sin6_len); - if (error == -1) { - close(wport6); - wport6 = -1; - goto passivefail; - } - error = listen(wport6, 1); - if (error == -1) { - close(wport6); - wport6 = -1; - goto passivefail; - } - - /* transmit LPSV or EPSV */ - /* - * addr from dst, port from wport6 - */ - len = sizeof(data6); - error = getsockname(wport6, (struct sockaddr *)&data6, &len); - if (error == -1) { - close(wport6); - wport6 = -1; - goto passivefail; - } - sin6 = (struct sockaddr_in6 *)&data6; - port = sin6->sin6_port; - - len = sizeof(data6); - error = getsockname(dst, (struct sockaddr *)&data6, &len); - if (error == -1) { - close(wport6); - wport6 = -1; - goto passivefail; - } - sin6 = (struct sockaddr_in6 *)&data6; - sin6->sin6_port = port; - - if (state == LPSV) { - a = (char *)&sin6->sin6_addr; - p = (char *)&sin6->sin6_port; - n = snprintf(sbuf, sizeof(sbuf), -"228 Entering Long Passive Mode (%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)\r\n", - 6, 16, UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), - UC(a[4]), UC(a[5]), UC(a[6]), UC(a[7]), - 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 >= 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 >= sizeof(sbuf)) - n = 0; - if (n) - write(dst, sbuf, n); - passivemode = 1; - return n; - } - } - } - - bad: - exit_failure("%s", strerror(errno)); - /*NOTREACHED*/ - return 0; /* to make gcc happy */ -} - -static int -ftp_copycommand(int src, int dst, enum state *state) -{ - int error, atmark, n; - socklen_t len; - unsigned int af, hal, ho[16], pal, po[2]; - 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); - if (error != -1 && atmark == 1) { - n = read(src, rbuf, 1); - if (n == -1) - goto bad; - send(dst, rbuf, n, MSG_OOB); -#if 0 - n = read(src, rbuf, sizeof(rbuf)); - if (n == -1) - goto bad; - write(dst, rbuf, n); - return n; -#endif - } - - n = read(src, rbuf, sizeof(rbuf)); - if (n <= 0) - return n; - rbuf[n] = '\0'; - - if (n < 4) { - write(dst, rbuf, n); - return n; - } - - /* - * parse argument - */ - p = rbuf; - q = cmd; - for (i = 0; i < 4; i++) { - if (!isalpha(*p)) { - /* invalid command */ - write(dst, rbuf, n); - return n; - } - *q++ = islower(*p) ? toupper(*p) : *p; - p++; - } - if (!isspace(*p)) { - /* invalid command */ - write(dst, rbuf, n); - return n; - } - *q = '\0'; - param = p; - /* param points to first non-command token, if any */ - while (*param && isspace(*param)) - param++; - if (!*param) - param = NULL; - - *state = NONE; - - if (strcmp(cmd, "LPRT") == 0 && param) { - /* - * LPRT -> PORT - */ - nstate = LPRT; - - close(wport4); - close(wport6); - close(port4); - close(port6); - wport4 = wport6 = port4 = port6 = -1; - - if (epsvall) { - n = snprintf(sbuf, sizeof(sbuf), "501 %s disallowed in EPSV ALL\r\n", - cmd); - if (n < 0 || n >= sizeof(sbuf)) - n = 0; - if (n) - write(src, sbuf, n); - return n; - } - - n = sscanf(param, -"%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u", - &af, &hal, &ho[0], &ho[1], &ho[2], &ho[3], - &ho[4], &ho[5], &ho[6], &ho[7], - &ho[8], &ho[9], &ho[10], &ho[11], - &ho[12], &ho[13], &ho[14], &ho[15], - &pal, &po[0], &po[1]); - if (n != 21 || af != 6 || hal != 16|| pal != 2) { - n = snprintf(sbuf, sizeof(sbuf), - "501 illegal parameter to LPRT\r\n"); - if (n < 0 || n >= sizeof(sbuf)) - n = 0; - if (n) - write(src, sbuf, n); - return n; - } - - /* keep LPRT parameter */ - memset(&data6, 0, sizeof(data6)); - sin6 = (struct sockaddr_in6 *)&data6; - sin6->sin6_len = sizeof(*sin6); - sin6->sin6_family = AF_INET6; - for (n = 0; n < 16; n++) - sin6->sin6_addr.s6_addr[n] = ho[n]; - sin6->sin6_port = htons(((po[0] & 0xff) << 8) | (po[1] & 0xff)); - -sendport: - /* get ready for active data connection */ - 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"); - 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; - sin = (struct sockaddr_in *)&data4; - sin->sin_port = 0; - wport4 = socket(sin->sin_family, SOCK_STREAM, 0); - if (wport4 == -1) - goto lprtfail; - error = bind(wport4, (struct sockaddr *)sin, sin->sin_len); - if (error == -1) { - close(wport4); - wport4 = -1; - goto lprtfail; - } - error = listen(wport4, 1); - if (error == -1) { - close(wport4); - wport4 = -1; - goto lprtfail; - } - - /* transmit PORT */ - len = sizeof(data4); - error = getsockname(wport4, (struct sockaddr *)&data4, &len); - if (error == -1) { - close(wport4); - wport4 = -1; - goto lprtfail; - } - if (((struct sockaddr *)&data4)->sa_family != AF_INET) { - close(wport4); - wport4 = -1; - goto lprtfail; - } - sin = (struct sockaddr_in *)&data4; - a = (char *)&sin->sin_addr; - p = (char *)&sin->sin_port; - 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 >= sizeof(sbuf)) - n = 0; - if (n) - write(dst, sbuf, n); - *state = nstate; - passivemode = 0; - return n; - } else if (strcmp(cmd, "EPRT") == 0 && param) { - /* - * EPRT -> PORT - */ - char *afp, *hostp, *portp; - struct addrinfo hints, *res; - - nstate = EPRT; - - close(wport4); - close(wport6); - close(port4); - close(port6); - wport4 = wport6 = port4 = port6 = -1; - - if (epsvall) { - n = snprintf(sbuf, sizeof(sbuf), "501 %s disallowed in EPSV ALL\r\n", - cmd); - if (n < 0 || n >= sizeof(sbuf)) - n = 0; - if (n) - write(src, sbuf, n); - return n; - } - - p = param; - ch = *p++; /* boundary character */ - afp = p; - while (*p && *p != ch) - p++; - if (!*p) { -eprtparamfail: - n = snprintf(sbuf, sizeof(sbuf), - "501 illegal parameter to EPRT\r\n"); - if (n < 0 || n >= sizeof(sbuf)) - n = 0; - if (n) - write(src, sbuf, n); - return n; - } - *p++ = '\0'; - hostp = p; - while (*p && *p != ch) - p++; - if (!*p) - goto eprtparamfail; - *p++ = '\0'; - portp = p; - while (*p && *p != ch) - p++; - if (!*p) - goto eprtparamfail; - *p++ = '\0'; - - n = sscanf(afp, "%d", &af); - if (n != 1 || af != 2) { - n = snprintf(sbuf, sizeof(sbuf), - "501 unsupported address family to EPRT\r\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)); - 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); - if (n < 0 || n >= sizeof(sbuf)) - n = 0; - if (n) - write(src, sbuf, n); - freeaddrinfo(res); - return n; - } - - memcpy(&data6, res->ai_addr, res->ai_addrlen); - - freeaddrinfo(res); - goto sendport; - } else if (strcmp(cmd, "LPSV") == 0 && !param) { - /* - * LPSV -> PASV - */ - nstate = LPSV; - - close(wport4); - close(wport6); - close(port4); - close(port6); - wport4 = wport6 = port4 = port6 = -1; - - if (epsvall) { - n = snprintf(sbuf, sizeof(sbuf), "501 %s disallowed in EPSV ALL\r\n", - cmd); - 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 >= sizeof(sbuf)) - n = 0; - if (n) - write(dst, sbuf, n); - *state = LPSV; - passivemode = 0; /* to be set to 1 later */ - return n; - } else if (strcmp(cmd, "EPSV") == 0 && !param) { - /* - * EPSV -> PASV - */ - close(wport4); - close(wport6); - close(port4); - close(port6); - wport4 = wport6 = port4 = port6 = -1; - - n = snprintf(sbuf, sizeof(sbuf), "PASV\r\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; - } else if (strcmp(cmd, "EPSV") == 0 && param - && strncasecmp(param, "ALL", 3) == 0 && isspace(param[3])) { - /* - * EPSV ALL - */ - epsvall = 1; - n = snprintf(sbuf, sizeof(sbuf), "200 EPSV ALL command successful.\r\n"); - if (n < 0 || n >= sizeof(sbuf)) - n = 0; - if (n) - write(src, sbuf, n); - return n; - } 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); - 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 - || strcmp(cmd, "RETR") == 0 - || strcmp(cmd, "LIST") == 0 - || strcmp(cmd, "NLST") == 0 - || strcmp(cmd, "APPE") == 0)) { - /* - * commands with data transfer. need to care about passive - * mode data connection. - */ - - if (ftp_passiveconn() < 0) { - n = snprintf(sbuf, sizeof(sbuf), "425 Cannot open data connetion\r\n"); - if (n < 0 || n >= sizeof(sbuf)) - n = 0; - if (n) - write(src, sbuf, n); - } else { - /* simply relay the command */ - write(dst, rbuf, n); - } - - *state = NONE; - return n; - } else { - /* simply relay it */ - *state = NONE; - write(dst, rbuf, n); - return n; - } - - bad: - exit_failure("%s", strerror(errno)); - /*NOTREACHED*/ - return 0; /* to make gcc happy */ -} diff --git a/usr.sbin/faithd/prefix.c b/usr.sbin/faithd/prefix.c deleted file mode 100644 index bdb763a..0000000 --- a/usr.sbin/faithd/prefix.c +++ /dev/null @@ -1,345 +0,0 @@ -/* $KAME: prefix.c,v 1.13 2003/09/02 22:50:17 itojun Exp $ */ -/* $FreeBSD$ */ - -/* - * Copyright (C) 2000 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. - */ - -#include <sys/types.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <stdio.h> -#include <netdb.h> -#include <string.h> -#include <stddef.h> -#include <stdlib.h> -#include <limits.h> - -#ifndef offsetof -#define offsetof(type, member) ((size_t)(u_long)(&((type *)0)->member)) -#endif - -#include "faithd.h" -#include "prefix.h" - -static int prefix_set(const char *, struct prefix *, int); -static struct config *config_load1(const char *); -#if 0 -static void config_show1(const struct config *); -static void config_show(void); -#endif - -struct config *config_list = NULL; -const int niflags = NI_NUMERICHOST; - -static int -prefix_set(const char *s, struct prefix *prefix, int slash) -{ - char *p = NULL, *q, *r; - struct addrinfo hints, *res = NULL; - int max; - - p = strdup(s); - if (!p) - goto fail; - q = strchr(p, '/'); - if (q) { - if (!slash) - goto fail; - *q++ = '\0'; - } - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = PF_UNSPEC; - hints.ai_socktype = SOCK_DGRAM; /*dummy*/ - hints.ai_flags = AI_NUMERICHOST; - if (getaddrinfo(p, "0", &hints, &res)) - goto fail; - if (res->ai_next || res->ai_addrlen > sizeof(prefix->a)) - goto fail; - memcpy(&prefix->a, res->ai_addr, res->ai_addrlen); - - switch (prefix->a.ss_family) { - case AF_INET: - max = 32; - break; - case AF_INET6: - max = 128; - break; - default: - max = -1; - break; - } - - if (q) { - r = NULL; - prefix->l = (int)strtoul(q, &r, 10); - if (!*q || *r) - goto fail; - if (prefix->l < 0 || prefix->l > max) - goto fail; - } else - prefix->l = max; - - if (p) - free(p); - if (res) - freeaddrinfo(res); - return 0; - -fail: - if (p) - free(p); - if (res) - freeaddrinfo(res); - return -1; -} - -const char * -prefix_string(const struct prefix *prefix) -{ - static char buf[NI_MAXHOST + 20]; - char hbuf[NI_MAXHOST]; - - if (getnameinfo((const struct sockaddr *)&prefix->a, prefix->a.ss_len, - hbuf, sizeof(hbuf), NULL, 0, niflags)) - return NULL; - snprintf(buf, sizeof(buf), "%s/%d", hbuf, prefix->l); - return buf; -} - -int -prefix_match(const struct prefix *prefix, const struct sockaddr *sa) -{ - struct sockaddr_storage a, b; - char *pa, *pb; - int off, l; - - if (prefix->a.ss_family != sa->sa_family || - prefix->a.ss_len != sa->sa_len) - return 0; - - if (prefix->a.ss_len > sizeof(a) || sa->sa_len > sizeof(b)) - return 0; - - switch (prefix->a.ss_family) { - case AF_INET: - off = offsetof(struct sockaddr_in, sin_addr); - break; - case AF_INET6: - off = offsetof(struct sockaddr_in6, sin6_addr); - break; - default: - if (memcmp(&prefix->a, sa, prefix->a.ss_len) != 0) - return 0; - else - return 1; - } - - memcpy(&a, &prefix->a, prefix->a.ss_len); - memcpy(&b, sa, sa->sa_len); - l = prefix->l / 8 + (prefix->l % 8 ? 1 : 0); - - /* overrun check */ - if (off + l > a.ss_len) - return 0; - - pa = ((char *)&a) + off; - pb = ((char *)&b) + off; - if (prefix->l % 8) { - pa[prefix->l / 8] &= 0xff00 >> (prefix->l % 8); - pb[prefix->l / 8] &= 0xff00 >> (prefix->l % 8); - } - if (memcmp(pa, pb, l) != 0) - return 0; - else - return 1; -} - -/* - * prefix/prefixlen permit/deny prefix/prefixlen [srcaddr] - * 3ffe::/16 permit 10.0.0.0/8 10.1.1.1 - */ -static struct config * -config_load1(const char *line) -{ - struct config *conf; - char buf[BUFSIZ]; - char *p; - char *token[4]; - int i; - - if (strlen(line) + 1 > sizeof(buf)) - return NULL; - strlcpy(buf, line, sizeof(buf)); - - p = strchr(buf, '\n'); - if (!p) - return NULL; - *p = '\0'; - p = strchr(buf, '#'); - if (p) - *p = '\0'; - if (strlen(buf) == 0) - return NULL; - - p = buf; - memset(token, 0, sizeof(token)); - for (i = 0; i < sizeof(token) / sizeof(token[0]); i++) { - token[i] = strtok(p, "\t "); - p = NULL; - if (token[i] == NULL) - break; - } - /* extra tokens? */ - if (strtok(p, "\t ") != NULL) - return NULL; - /* insufficient tokens */ - switch (i) { - case 3: - case 4: - break; - default: - return NULL; - } - - conf = (struct config *)malloc(sizeof(*conf)); - if (conf == NULL) - return NULL; - memset(conf, 0, sizeof(*conf)); - - if (strcasecmp(token[1], "permit") == 0) - conf->permit = 1; - else if (strcasecmp(token[1], "deny") == 0) - conf->permit = 0; - else { - /* invalid keyword is considered as "deny" */ - conf->permit = 0; - } - - if (prefix_set(token[0], &conf->match, 1) < 0) - goto fail; - if (prefix_set(token[2], &conf->dest, 1) < 0) - goto fail; - if (token[3]) { - if (prefix_set(token[3], &conf->src, 0) < 0) - goto fail; - } - - return conf; - -fail: - free(conf); - return NULL; -} - -int -config_load(const char *configfile) -{ - FILE *fp; - char buf[BUFSIZ]; - struct config *conf, *p; - struct config sentinel; - - config_list = NULL; - - if (!configfile) - configfile = _PATH_PREFIX_CONF; - fp = fopen(configfile, "r"); - if (fp == NULL) - return -1; - - p = &sentinel; - sentinel.next = NULL; - while (fgets(buf, sizeof(buf), fp) != NULL) { - conf = config_load1(buf); - if (conf) { - p->next = conf; - p = p->next; - } - } - config_list = sentinel.next; - - fclose(fp); - return 0; -} - -#if 0 -static void -config_show1(const struct config *conf) -{ - const char *p; - - p = prefix_string(&conf->match); - printf("%s", p ? p : "?"); - - if (conf->permit) - printf(" permit"); - else - printf(" deny"); - - p = prefix_string(&conf->dest); - printf(" %s", p ? p : "?"); - - printf("\n"); -} - -static void -config_show() -{ - struct config *conf; - - for (conf = config_list; conf; conf = conf->next) - config_show1(conf); -} -#endif - -const struct config * -config_match(struct sockaddr *sa1, struct sockaddr *sa2) -{ - static struct config conf; - const struct config *p; - - if (sa1->sa_len > sizeof(conf.match.a) || - sa2->sa_len > sizeof(conf.dest.a)) - return NULL; - - memset(&conf, 0, sizeof(conf)); - if (!config_list) { - conf.permit = 1; - memcpy(&conf.match.a, sa1, sa1->sa_len); - memcpy(&conf.dest.a, sa2, sa2->sa_len); - return &conf; - } - - for (p = config_list; p; p = p->next) - if (prefix_match(&p->match, sa1) && prefix_match(&p->dest, sa2)) - return p; - - return NULL; -} diff --git a/usr.sbin/faithd/prefix.h b/usr.sbin/faithd/prefix.h deleted file mode 100644 index 4d6b3d5..0000000 --- a/usr.sbin/faithd/prefix.h +++ /dev/null @@ -1,52 +0,0 @@ -/* $KAME: prefix.h,v 1.4 2001/09/05 03:04:21 itojun Exp $ */ -/* $FreeBSD$ */ - -/* - * Copyright (C) 2000 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. - */ - -struct prefix { - struct sockaddr_storage a; - int l; -}; - -struct config { - struct config *next; - - int permit; - struct prefix match; - struct prefix dest; - struct prefix src; /* src to use for outgoing connection */ -}; - -#define _PATH_PREFIX_CONF "/etc/faithd.conf" - -extern const char *prefix_string(const struct prefix *); -extern int prefix_match(const struct prefix *, const struct sockaddr *); -extern int config_load(const char *); -extern const struct config *config_match(struct sockaddr *, struct sockaddr *); diff --git a/usr.sbin/faithd/tcp.c b/usr.sbin/faithd/tcp.c deleted file mode 100644 index 2197694..0000000 --- a/usr.sbin/faithd/tcp.c +++ /dev/null @@ -1,324 +0,0 @@ -/* $KAME: tcp.c,v 1.13 2003/09/02 22:49:21 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. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/ioctl.h> -#include <sys/time.h> -#include <sys/wait.h> - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <syslog.h> -#include <unistd.h> -#include <errno.h> -#include <fcntl.h> -#include <signal.h> - -#include <netinet/in.h> -#include <arpa/inet.h> -#include <netdb.h> - -#include "faithd.h" - -static char tcpbuf[16*1024]; - /* bigger than MSS and may be lesser than window size */ -static int tblen, tboff, oob_exists; -static fd_set readfds, writefds, exceptfds; -static char atmark_buf[2]; -static pid_t cpid = (pid_t)0; -static pid_t ppid = (pid_t)0; -volatile time_t child_lastactive = (time_t)0; -static time_t parent_lastactive = (time_t)0; - -static void sig_ctimeout(int); -static void sig_child(int); -static void notify_inactive(void); -static void notify_active(void); -static void send_data(int, int, const char *, int); -static void relay(int, int, const char *, int); - -/* - * Inactivity timer: - * - child side (ppid != 0) will send SIGUSR1 to parent every (FAITH_TIMEOUT/4) - * second if traffic is active. if traffic is inactive, don't send SIGUSR1. - * - parent side (ppid == 0) will check the last SIGUSR1 it have seen. - */ -static void -sig_ctimeout(int sig __unused) -{ - /* parent side: record notification from the child */ - if (dflag) - syslog(LOG_DEBUG, "activity timer from child"); - child_lastactive = time(NULL); -} - -/* parent will terminate if child dies. */ -static void -sig_child(int sig __unused) -{ - int status; - pid_t pid; - - pid = wait3(&status, WNOHANG, (struct rusage *)0); - 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"); -} - -static void -notify_inactive() -{ - time_t t; - - /* only on parent side... */ - if (ppid) - return; - - /* parent side should check for timeout. */ - t = time(NULL); - if (dflag) { - syslog(LOG_DEBUG, "parent side %sactive, child side %sactive", - (FAITH_TIMEOUT < t - parent_lastactive) ? "in" : "", - (FAITH_TIMEOUT < t - child_lastactive) ? "in" : ""); - } - - if (FAITH_TIMEOUT < t - child_lastactive - && FAITH_TIMEOUT < t - parent_lastactive) { - /* both side timeouted */ - signal(SIGCHLD, SIG_DFL); - kill(cpid, SIGTERM); - wait(NULL); - exit_failure("connection timeout"); - /* NOTREACHED */ - } -} - -static void -notify_active() -{ - if (ppid) { - /* child side: notify parent of active traffic */ - time_t t; - t = time(NULL); - if (FAITH_TIMEOUT / 4 < t - child_lastactive) { - if (kill(ppid, SIGUSR1) < 0) { - exit_failure("terminate connection due to parent termination"); - /* NOTREACHED */ - } - child_lastactive = t; - } - } else { - /* parent side */ - parent_lastactive = time(NULL); - } -} - -static void -send_data(int s_rcv, int s_snd, const char *service __unused, int direction) -{ - int cc; - - if (oob_exists) { - cc = send(s_snd, atmark_buf, 1, MSG_OOB); - 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); - } - - for (; tboff < tblen; tboff += cc) { - cc = write(s_snd, tcpbuf + tboff, tblen - tboff); - if (cc < 0) - goto retry_or_err; - } -#ifdef DEBUG - if (tblen) { - if (tblen >= sizeof(tcpbuf)) - tblen = sizeof(tcpbuf) - 1; - tcpbuf[tblen] = '\0'; - syslog(LOG_DEBUG, "from %s (%dbytes): %s", - direction == 1 ? "client" : "server", tblen, tcpbuf); - } -#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); -} - -static void -relay(int s_rcv, int s_snd, const char *service, int direction) -{ - int atmark, error, maxfd; - struct timeval tv; - fd_set oreadfds, owritefds, oexceptfds; - - FD_ZERO(&readfds); - FD_ZERO(&writefds); - 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; - maxfd = (s_rcv > s_snd) ? s_rcv : s_snd; - - for (;;) { - tv.tv_sec = FAITH_TIMEOUT / 4; - tv.tv_usec = 0; - oreadfds = readfds; - owritefds = writefds; - oexceptfds = exceptfds; - error = select(maxfd + 1, &readfds, &writefds, &exceptfds, &tv); - if (error == -1) { - if (errno == EINTR) - continue; - exit_failure("select: %s", strerror(errno)); - } else if (error == 0) { - readfds = oreadfds; - writefds = owritefds; - exceptfds = oexceptfds; - notify_inactive(); - continue; - } - - /* activity notification */ - notify_active(); - - if (FD_ISSET(s_rcv, &exceptfds)) { - error = ioctl(s_rcv, SIOCATMARK, &atmark); - if (error != -1 && atmark == 1) { - int cc; - 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) { - if (errno == EINTR) - goto oob_read_retry; - exit_failure("reading oob data failed" - ": %s", - strerror(errno)); - } - } - } - if (FD_ISSET(s_rcv, &readfds)) { - relaydata_read_retry: - tblen = read(s_rcv, tcpbuf, sizeof(tcpbuf)); - tboff = 0; - - switch (tblen) { - case -1: - if (errno == EINTR) - goto relaydata_read_retry; - exit_failure("reading relay data failed: %s", - strerror(errno)); - /* NOTREACHED */ - case 0: - /* to close opposite-direction relay process */ - shutdown(s_snd, 0); - - close(s_rcv); - close(s_snd); - 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; - } - } - if (FD_ISSET(s_snd, &writefds)) - send_data(s_rcv, s_snd, service, direction); - } -} - -void -tcp_relay(int s_src, int s_dst, const char *service) -{ - syslog(LOG_INFO, "starting %s relay", service); - - child_lastactive = parent_lastactive = time(NULL); - - cpid = fork(); - switch (cpid) { - case -1: - exit_failure("tcp_relay: can't fork grand child: %s", - strerror(errno)); - /* NOTREACHED */ - case 0: - /* child process: relay going traffic */ - ppid = getppid(); - /* this is child so reopen log */ - closelog(); - openlog(logname, LOG_PID | LOG_NOWAIT, LOG_DAEMON); - relay(s_src, s_dst, service, 1); - /* NOTREACHED */ - default: - /* parent process: relay coming traffic */ - ppid = (pid_t)0; - signal(SIGUSR1, sig_ctimeout); - signal(SIGCHLD, sig_child); - relay(s_dst, s_src, service, 0); - /* NOTREACHED */ - } -} diff --git a/usr.sbin/faithd/test/faithd.rb b/usr.sbin/faithd/test/faithd.rb deleted file mode 100644 index 682f540..0000000 --- a/usr.sbin/faithd/test/faithd.rb +++ /dev/null @@ -1,312 +0,0 @@ -# faithd, ruby version. requires v6-enabled ruby. -# -# highly experimental (not working right at all) and very limited -# functionality. -# -# $Id: faithd.rb,v 1.1.2.4 1999/05/10 17:06:30 itojun Exp $ -# $FreeBSD$ - -require "socket" -require "thread" - -# XXX should be derived from system headers -IPPROTO_IPV6 = 41 -IPV6_FAITH = 29 -DEBUG = true -DEBUG_LOOPBACK = true - -# TODO: OOB data handling -def tcpcopy(s1, s2, m) - STDERR.print "tcpcopy #{s1} #{s2}\n" if DEBUG - buf = "" - while TRUE - begin - buf = s1.sysread(100) - s2.syswrite(buf) - rescue EOFError - break - rescue IOError - break - end - end - STDERR.print "tcpcopy #{s1} #{s2} finished\n" if DEBUG - s1.shutdown(0) - s2.shutdown(1) -end - -def relay_ftp_passiveconn(s6, s4, dport6, dport4) - Thread.start do - d6 = TCPserver.open("::", dport6).accept - d4 = TCPsocket.open(s4.getpeer[3], dport4) - t = [] - t[0] = Thread.start do - tcpcopy(d6, d4) - end - t[1] = Thread.start do - tcpcopy(d4, d6) - end - for i in t - i.join - end - d4.close - d6.close - end -end - -def ftp_parse_2428(line) - if (line[0] != line[line.length - 1]) - return nil - end - t = line.split(line[0 .. 0]) # as string - if (t.size != 4 || t[1] !~ /^[12]$/ || t[3] !~ /^\d+$/) - return nil - end - return t[1 .. 3] -end - -def relay_ftp_command(s6, s4, state) - STDERR.print "relay_ftp_command start\n" if DEBUG - while TRUE - begin - STDERR.print "s6.gets\n" if DEBUG - line = s6.gets - STDERR.print "line is #{line}\n" if DEBUG - if line == nil - return nil - end - - # translate then copy - STDERR.print "line is #{line}\n" if DEBUG - if (line =~ /^EPSV\r\n/i) - STDERR.print "EPSV -> PASV\n" if DEBUG - line = "PASV\n" - state = "EPSV" - elsif (line =~ /^EPRT\s+(.+)\r\n/i) - t = ftp_parse_2428($1) - if t == nil - s6.puts "501 illegal parameter to EPRT\r\n" - next - end - - # some tricks should be here - s6.puts "501 illegal parameter to EPRT\r\n" - next - end - STDERR.print "fail: send #{line} as is\n" if DEBUG - s4.puts(line) - break - rescue EOFError - return nil - rescue IOError - return nil - end - end - STDERR.print "relay_ftp_command finish\n" if DEBUG - return state -end - -def relay_ftp_status(s4, s6, state) - STDERR.print "relay_ftp_status start\n" if DEBUG - while TRUE - begin - line = s4.gets - if line == nil - return nil - end - - # translate then copy - s6.puts(line) - - next if line =~ /^\d\d\d-/ - next if line !~ /^\d/ - - # special post-processing - case line - when /^221 / # result to QUIT - s4.shutdown(0) - s6.shutdown(1) - end - - break if (line =~ /^\d\d\d /) - rescue EOFError - return nil - rescue IOError - return nil - end - end - STDERR.print "relay_ftp_status finish\n" if DEBUG - return state -end - -def relay_ftp(sock, name) - STDERR.print "relay_ftp(#{sock}, #{name})\n" if DEBUG - while TRUE - STDERR.print "relay_ftp(#{sock}, #{name}) accepting\n" if DEBUG - s = sock.accept - STDERR.print "relay_ftp(#{sock}, #{name}) accepted #{s}\n" if DEBUG - Thread.start do - threads = [] - STDERR.print "accepted #{s} -> #{Thread.current}\n" if DEBUG - s6 = s - dest6 = s.addr[3] - if !DEBUG_LOOPBACK - t = s.getsockname.unpack("x8 x12 C4") - dest4 = "#{t[0]}.#{t[1]}.#{t[2]}.#{t[3]}" - port4 = s.addr[1] - else - dest4 = "127.0.0.1" - port4 = "ftp" - end - if DEBUG - STDERR.print "IPv6 dest: #{dest6} IPv4 dest: #{dest4}\n" if DEBUG - end - STDERR.print "connect to #{dest4} #{port4}\n" if DEBUG - s4 = TCPsocket.open(dest4, port4) - STDERR.print "connected to #{dest4} #{port4}, #{s4.addr[1]}\n" if DEBUG - state = 0 - while TRUE - # translate status line - state = relay_ftp_status(s4, s6, state) - break if state == nil - # translate command line - state = relay_ftp_command(s6, s4, state) - break if state == nil - end - STDERR.print "relay_ftp(#{sock}, #{name}) closing s4\n" if DEBUG - s4.close - STDERR.print "relay_ftp(#{sock}, #{name}) closing s6\n" if DEBUG - s6.close - STDERR.print "relay_ftp(#{sock}, #{name}) done\n" if DEBUG - end - end - STDERR.print "relay_ftp(#{sock}, #{name}) finished\n" if DEBUG -end - -def relay_tcp(sock, name) - STDERR.print "relay_tcp(#{sock}, #{name})\n" if DEBUG - while TRUE - STDERR.print "relay_tcp(#{sock}, #{name}) accepting\n" if DEBUG - s = sock.accept - STDERR.print "relay_tcp(#{sock}, #{name}) accepted #{s}\n" if DEBUG - Thread.start do - threads = [] - STDERR.print "accepted #{s} -> #{Thread.current}\n" if DEBUG - s6 = s - dest6 = s.addr[3] - if !DEBUG_LOOPBACK - t = s.getsockname.unpack("x8 x12 C4") - dest4 = "#{t[0]}.#{t[1]}.#{t[2]}.#{t[3]}" - port4 = s.addr[1] - else - dest4 = "127.0.0.1" - port4 = "telnet" - end - if DEBUG - STDERR.print "IPv6 dest: #{dest6} IPv4 dest: #{dest4}\n" if DEBUG - end - STDERR.print "connect to #{dest4} #{port4}\n" if DEBUG - s4 = TCPsocket.open(dest4, port4) - STDERR.print "connected to #{dest4} #{port4}, #{s4.addr[1]}\n" if DEBUG - [0, 1].each do |i| - threads[i] = Thread.start do - if (i == 0) - tcpcopy(s6, s4) - else - tcpcopy(s4, s6) - end - end - end - STDERR.print "relay_tcp(#{sock}, #{name}) wait\n" if DEBUG - for i in threads - STDERR.print "relay_tcp(#{sock}, #{name}) wait #{i}\n" if DEBUG - i.join - STDERR.print "relay_tcp(#{sock}, #{name}) wait #{i} done\n" if DEBUG - end - STDERR.print "relay_tcp(#{sock}, #{name}) closing s4\n" if DEBUG - s4.close - STDERR.print "relay_tcp(#{sock}, #{name}) closing s6\n" if DEBUG - s6.close - STDERR.print "relay_tcp(#{sock}, #{name}) done\n" if DEBUG - end - end - STDERR.print "relay_tcp(#{sock}, #{name}) finished\n" if DEBUG -end - -def usage() - STDERR.print "usage: #{$0} [-f] port...\n" -end - -#------------------------------------------------------------ - -$mode = "tcp" - -while ARGV[0] =~ /^-/ do - case ARGV[0] - when /^-f/ - $mode = "ftp" - else - usage() - exit 0 - end - ARGV.shift -end - -if ARGV.length == 0 - usage() - exit 1 -end - -ftpport = Socket.getservbyname("ftp") - -res = [] -for port in ARGV - t = Socket.getaddrinfo(nil, port, Socket::PF_INET6, Socket::SOCK_STREAM, - nil, Socket::AI_PASSIVE) - if (t.size <= 0) - STDERR.print "FATAL: getaddrinfo failed (port=#{port})\n" - exit 1 - end - res += t -end - -sockpool = [] -names = [] -listenthreads = [] - -res.each do |i| - s = TCPserver.new(i[3], i[1]) - n = Socket.getnameinfo(s.getsockname, Socket::NI_NUMERICHOST|Socket::NI_NUMERICSERV).join(" port ") - if i[6] == IPPROTO_IPV6 - s.setsockopt(i[6], IPV6_FAITH, 1) - end - s.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1) - sockpool.push s - names.push n -end - -if DEBUG - (0 .. sockpool.size - 1).each do |i| - STDERR.print "listen[#{i}]: #{sockpool[i]} #{names[i]}\n" if DEBUG - end -end - -(0 .. sockpool.size - 1).each do |i| - listenthreads[i] = Thread.start do - if DEBUG - STDERR.print "listen[#{i}]: thread #{Thread.current}\n" if DEBUG - end - STDERR.print "listen[#{i}]: thread #{Thread.current}\n" if DEBUG - case $mode - when "tcp" - relay_tcp(sockpool[i], names[i]) - when "ftp" - relay_ftp(sockpool[i], names[i]) - end - end -end - -for i in listenthreads - i.join -end - -exit 0 diff --git a/usr.sbin/ftp-proxy/ftp-proxy/Makefile b/usr.sbin/ftp-proxy/ftp-proxy/Makefile deleted file mode 100644 index 686bac4..0000000 --- a/usr.sbin/ftp-proxy/ftp-proxy/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -# $FreeBSD$ - -.PATH: ${.CURDIR}/../../../contrib/pf/ftp-proxy - -PROG= ftp-proxy -MAN= ftp-proxy.8 - -SRCS= ftp-proxy.c filter.c - -CFLAGS+= -I${.CURDIR}/../../../contrib/pf/libevent - -LDADD+= ${LIBEVENT} -DPADD+= ${LIBEVENT} - -WARNS?= 3 - -NO_PIE= yes - -.include <bsd.prog.mk> diff --git a/usr.sbin/ftp-proxy/ftp-proxy/Makefile.depend b/usr.sbin/ftp-proxy/ftp-proxy/Makefile.depend deleted file mode 100644 index bbe5cc8..0000000 --- a/usr.sbin/ftp-proxy/ftp-proxy/Makefile.depend +++ /dev/null @@ -1,21 +0,0 @@ -# Autogenerated - do NOT edit! - -DEP_RELDIR := ${_PARSEDIR:S,${SRCTOP}/,,} - -DIRDEPS = \ - gnu/lib/csu \ - gnu/lib/libgcc \ - include \ - include/arpa \ - include/xlocale \ - lib/${CSU_DIR} \ - lib/libc \ - lib/libcompiler_rt \ - usr.sbin/ftp-proxy/libevent \ - - -.include <dirdeps.mk> - -.if ${DEP_RELDIR} == ${_DEP_RELDIR} -# local dependencies - needed for -jN in clean tree -.endif diff --git a/usr.sbin/ftp-proxy/libevent/Makefile b/usr.sbin/ftp-proxy/libevent/Makefile deleted file mode 100644 index a8ff09b..0000000 --- a/usr.sbin/ftp-proxy/libevent/Makefile +++ /dev/null @@ -1,27 +0,0 @@ -# $FreeBSD$ - -.PATH: ${.CURDIR}/../../../contrib/pf/libevent - - -LIB= event -INTERNALLIB=yes -SRCS= buffer.c evbuffer.c event.c kqueue.c log.c poll.c select.c signal.c -HDRS= event.h - -CFLAGS+= -I${.CURDIR} \ - -DHAVE_CLOCK_GETTIME \ - -DHAVE_FCNTL_H \ - -DHAVE_POLL \ - -DHAVE_SELECT \ - -DHAVE_SETFD \ - -DHAVE_STDARG_H \ - -DHAVE_SYS_IOCTL_H \ - -DHAVE_SYS_TIME_H \ - -DHAVE_UNISTD_H \ - -DHAVE_VASPRINTF \ - -DHAVE_WORKING_KQUEUE \ - -DVERSION='"1.3b"' - -WARNS?= 2 - -.include <bsd.lib.mk> diff --git a/usr.sbin/ftp-proxy/libevent/Makefile.depend b/usr.sbin/ftp-proxy/libevent/Makefile.depend deleted file mode 100644 index 639d45d..0000000 --- a/usr.sbin/ftp-proxy/libevent/Makefile.depend +++ /dev/null @@ -1,14 +0,0 @@ -# Autogenerated - do NOT edit! - -DEP_RELDIR := ${_PARSEDIR:S,${SRCTOP}/,,} - -DIRDEPS = \ - include \ - include/xlocale \ - - -.include <dirdeps.mk> - -.if ${DEP_RELDIR} == ${_DEP_RELDIR} -# local dependencies - needed for -jN in clean tree -.endif |