# xargs -n1 | sort | uniq -d;
# done
+# 20141109: faith/faithd removal
+OLD_FILES+=etc/rc.d/faith
+OLD_FILES+=usr/share/man/man4/faith.4.gz
+OLD_FILES+=usr/share/man/man4/if_faith.4.gz
+OLD_FILES+=usr/sbin/faithd
+OLD_FILES+=usr/share/man/man8/faithd.8.gz
# 20141102: postrandom obsoleted by new /dev/random code
OLD_FILES+=etc/rc.d/postrandom
# 20141031: initrandom obsoleted by new /dev/random code
disable the most expensive debugging functionality run
"ln -s 'abort:false,junk:false' /etc/malloc.conf".)
+20141109:
+ faith(4) and faithd(8) has been removed from base system. It
+ has been obsolete for a very long time.
+
20141104:
vt(4), the new console driver, is enabled by default. It brings
support for Unicode and double-width characters, as well as
stf_interface_ipv6_ifid="0:0:0:1" # IPv6 interface id for stf0.
# If you like, you can set "AUTO" for this.
stf_interface_ipv6_slaid="0000" # IPv6 Site Level Aggregator for stf0
-ipv6_faith_prefix="NO" # Set faith prefix to enable a FAITH
- # IPv6-to-IPv4 TCP translator. You also need
- # faithd(8) setup.
ipv6_ipv4mapping="NO" # Set to "YES" to enable IPv4 mapped IPv6 addr
# communication. (like ::ffff:a.b.c.d)
ipv6_ipfilter_rules="/etc/ipf6.rules" # rules definition file for ipfilter,
case $1 in
lo[0-9]*|\
stf[0-9]*|\
- faith[0-9]*|\
lp[0-9]*|\
sl[0-9]*)
return 1
case $_if in
lo[0-9]*|\
stf[0-9]*|\
- faith[0-9]*|\
lp[0-9]*|\
sl[0-9]*)
return 1
dhclient \
dmesg \
dumpon \
- faith \
fsck \
ftpd \
gbde \
#
# PROVIDE: NETWORKING NETWORK
-# REQUIRE: netif netoptions routing ppp ipfw stf faith
+# REQUIRE: netif netoptions routing ppp ipfw stf
# REQUIRE: defaultroute routed mrouted route6d mroute6d resolv bridge
# REQUIRE: static_arp static_ndp local_unbound
#
# PROVIDE: bridge
-# REQUIRE: netif faith ppp stf
+# REQUIRE: netif ppp stf
# KEYWORD: nojail
. /etc/rc.subr
#
# PROVIDE: defaultroute
-# REQUIRE: devd faith netif stf
+# REQUIRE: devd netif stf
# KEYWORD: nojail
. /etc/rc.subr
+++ /dev/null
-#!/bin/sh
-# $FreeBSD$
-#
-
-# PROVIDE: faith
-# REQUIRE: netif
-# KEYWORD: nojail
-
-. /etc/rc.subr
-. /etc/network.subr
-
-name="faith"
-start_cmd="faith_up"
-stop_cmd="faith_down"
-
-faith_up()
-{
- case ${ipv6_faith_prefix} in
- [Nn][Oo] | '')
- ;;
- *)
- echo "Configuring IPv6-to-IPv4 TCP relay capturing interface:" \
- " faith0."
- ${SYSCTL} net.inet6.ip6.keepfaith=1
- ifconfig faith0 create >/dev/null 2>&1
- ifconfig faith0 up
- for prefix in ${ipv6_faith_prefix}; do
- prefixlen=`expr "${prefix}" : ".*/\(.*\)"`
- case ${prefixlen} in
- '')
- prefixlen=96
- ;;
- *)
- prefix=`expr "${prefix}" : \
- "\(.*\)/${prefixlen}"`
- ;;
- esac
- route add -inet6 ${prefix} -prefixlen ${prefixlen} ::1
- route change -inet6 ${prefix} -prefixlen ${prefixlen} \
- -ifp faith0
- done
- check_startmsgs && ifconfig faith0
- ;;
- esac
-}
-
-faith_down()
-{
- echo "Removing IPv6-to-IPv4 TCP relay capturing interface: faith0."
- ifconfig faith0 destroy
- ${SYSCTL} net.inet6.ip6.keepfaith=0
-
- case ${ipv6_faith_prefix} in
- [Nn][Oo] | '')
- ;;
- *)
- for prefix in ${ipv6_faith_prefix}; do
- prefixlen=`expr "${prefix}" : ".*/\(.*\)"`
- case ${prefixlen} in
- '')
- prefixlen=96
- ;;
- *)
- prefix=`expr "${prefix}" : \
- "\(.*\)/${prefixlen}"`
- ;;
- esac
- route delete -inet6 ${prefix} -prefixlen ${prefixlen}
- done
- ;;
- esac
-}
-
-load_rc_config $name
-run_rc_command "$1"
#
# PROVIDE: routing
-# REQUIRE: faith netif ppp stf
+# REQUIRE: netif ppp stf
# KEYWORD: nojailvnet
. /etc/rc.subr
[Nn][Oo][Nn][Ee])
return
;;
- lo0|faith[0-9]*)
+ lo0)
continue
;;
esac
*/
/*
- * "#ifdef FAITH" part is local hack for supporting IPv4-v6 translator.
- *
* Issues to be discussed:
* - Return values. There are nonstandard return values defined and used
* in the source code. This is because RFC2553 is silent about which error
#include "nscache.h"
#endif
-#if defined(__KAME__) && defined(INET6)
-# define FAITH
-#endif
-
#define ANY 0
#define YES 1
#define NO 0
{
char *p;
struct addrinfo *ai;
-#ifdef FAITH
- struct in6_addr faith_prefix;
- char *fp_str;
- int translate = 0;
-#endif
-
-#ifdef FAITH
- /*
- * Transfrom an IPv4 addr into a special IPv6 addr format for
- * IPv6->IPv4 translation gateway. (only TCP is supported now)
- *
- * +-----------------------------------+------------+
- * | faith prefix part (12 bytes) | embedded |
- * | | IPv4 addr part (4 bytes)
- * +-----------------------------------+------------+
- *
- * faith prefix part is specified as ascii IPv6 addr format
- * in environmental variable GAI.
- * For FAITH to work correctly, routing to faith prefix must be
- * setup toward a machine where a FAITH daemon operates.
- * Also, the machine must enable some mechanizm
- * (e.g. faith interface hack) to divert those packet with
- * faith prefixed destination addr to user-land FAITH daemon.
- */
- fp_str = getenv("GAI");
- if (fp_str && inet_pton(AF_INET6, fp_str, &faith_prefix) == 1 &&
- afd->a_af == AF_INET && pai->ai_socktype == SOCK_STREAM) {
- u_int32_t v4a;
- u_int8_t v4a_top;
-
- memcpy(&v4a, addr, sizeof v4a);
- v4a_top = v4a >> IN_CLASSA_NSHIFT;
- if (!IN_MULTICAST(v4a) && !IN_EXPERIMENTAL(v4a) &&
- v4a_top != 0 && v4a != IN_LOOPBACKNET) {
- afd = &afdl[N_INET6];
- memcpy(&faith_prefix.s6_addr[12], addr,
- sizeof(struct in_addr));
- translate = 1;
- }
- }
-#endif
ai = (struct addrinfo *)malloc(sizeof(struct addrinfo)
+ (afd->a_socklen));
ai->ai_addrlen = afd->a_socklen;
ai->ai_addr->sa_family = ai->ai_family = afd->a_af;
p = (char *)(void *)(ai->ai_addr);
-#ifdef FAITH
- if (translate == 1)
- memcpy(p + afd->a_off, &faith_prefix, (size_t)afd->a_addrlen);
- else
-#endif
memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen);
return ai;
}
/*
* The following have zero-length addresses.
* IFT_ATM (net/if_atmsubr.c)
- * IFT_FAITH (net/if_faith.c)
* IFT_GIF (net/if_gif.c)
* IFT_LOOP (net/if_loop.c)
* IFT_PPP (net/if_ppp.c, net/if_spppsubr.c)
device pty # Pseudo-ttys (telnet etc)
device md # Memory "disks"
#device gif 4 # IPv6 and IPv4 tunneling
-#device faith 1 # IPv6-to-IPv4 relaying (translation)
device tap
#options DEVICE_POLLING
device pty # Pseudo-ttys (telnet etc)
device md # Memory "disks"
#device gif 4 # IPv6 and IPv4 tunneling
-#device faith 1 # IPv6-to-IPv4 relaying (translation)
device tap
#options VIMAGE # soner or later we may want to test this
et.4 \
eventtimers.4 \
exca.4 \
- faith.4 \
fatm.4 \
fd.4 \
fdc.4 \
MLINKS+=enc.4 if_enc.4
MLINKS+=epair.4 if_epair.4
MLINKS+=et.4 if_et.4
-MLINKS+=faith.4 if_faith.4
MLINKS+=fatm.4 if_fatm.4
MLINKS+=fd.4 stderr.4 \
fd.4 stdin.4 \
+++ /dev/null
-.\" $KAME: faith.4,v 1.9 2001/04/27 17:26:35 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 January 23, 2012
-.Dt FAITH 4
-.Os
-.Sh NAME
-.Nm faith
-.Nd IPv6-to-IPv4 TCP relay capturing interface
-.Sh SYNOPSIS
-.Cd "device faith"
-.Sh DESCRIPTION
-The
-.Nm
-interface captures IPv6 TCP traffic,
-for implementing userland IPv6-to-IPv4 TCP relay
-like
-.Xr faithd 8 .
-.Pp
-Each
-.Nm
-interface is created at runtime using interface cloning.
-This is
-most easily done with the
-.Xr ifconfig 8
-.Cm create
-command or using the
-.Va cloned_interfaces
-variable in
-.Xr rc.conf 5 .
-.Pp
-Special action will be taken when IPv6 TCP traffic is seen on a router,
-and the default routing table suggests to route it to the
-.Nm
-interface.
-In this case, the packet will be accepted by the router,
-regardless of the list of IPv6 interface addresses assigned to the router.
-The packet will be captured by an IPv6 TCP socket, if it has the
-.Dv IN6P_FAITH
-flag turned on and matching address/port pairs.
-As a result,
-.Nm
-will let you capture IPv6 TCP traffic to some specific destination addresses.
-Userland programs, such as
-.Xr faithd 8
-can use this behavior to relay IPv6 TCP traffic to IPv4 TCP traffic.
-The program can accept some specific IPv6 TCP traffic, perform
-.Xr getsockname 2
-to get the IPv6 destination address specified by the client,
-and perform application-specific address mapping to relay IPv6 TCP to IPv4 TCP.
-.Pp
-The
-.Dv IN6P_FAITH
-flag on a IPv6 TCP socket can be set by using
-.Xr setsockopt 2 ,
-with level
-.Dv IPPROTO_IPV6
-and optname
-.Dv IPv6_FAITH .
-.Pp
-To handle error reports by ICMPv6, some ICMPv6 packets routed to an
-.Nm
-interface will be delivered to IPv6 TCP, as well.
-.Pp
-To understand how
-.Nm
-can be used, take a look at the source code of
-.Xr faithd 8 .
-.Pp
-As the
-.Nm
-interface implements potentially dangerous operations,
-great care must be taken when configuring it.
-To avoid possible misuse, the
-.Xr sysctl 8
-variable
-.Li net.inet6.ip6.keepfaith
-must be set to
-.Li 1
-prior to using the interface.
-When
-.Li net.inet6.ip6.keepfaith
-is
-.Li 0 ,
-no packets will be captured by the
-.Nm
-interface.
-.Pp
-The
-.Nm
-interface is intended to be used on routers, not on hosts.
-.\"
-.Sh SEE ALSO
-.Xr inet 4 ,
-.Xr inet6 4 ,
-.Xr faithd 8
-.Rs
-.%A Jun-ichiro itojun Hagino
-.%A Kazu Yamamoto
-.%T "An IPv6-to-IPv4 transport relay translator"
-.%O RFC3142
-.Re
-.Sh HISTORY
-The FAITH IPv6-to-IPv4 TCP relay translator first appeared in the
-WIDE hydrangea IPv6 stack.
Boolean: the default value of a per-interface flag to
enable/disable performing automatic link-local address configuration.
Defaults to on.
-.It Dv IPV6CTL_KEEPFAITH
-.Pq ip6.keepfaith
-Boolean: enable/disable
-.Dq FAITH
-TCP relay IPv6-to-IPv4 translator code in the kernel.
-Refer
-.Xr faith 4
-and
-.Xr faithd 8
-for detail.
-Defaults to off.
.It Dv IPV6CTL_LOG_INTERVAL
.Pq ip6.log_interval
Integer: default interval between
.\".Ox
.\"IPv6 sockets are always IPv6-only, so the socket option is read-only
.\"(not modifiable).
-.It Dv IPV6_FAITH Fa "int *"
-Get or set the status of whether
-.Xr faith 4
-connections can be made to this socket.
.It Dv IPV6_USE_MIN_MTU Fa "int *"
Get or set whether the minimal IPv6 maximum transmission unit (MTU) size
will be used to avoid fragmentation from occurring for subsequent
.Pq Vt str
IPv6 Site Level Aggregator for
.Xr stf 4 .
-.It Va ipv6_faith_prefix
-.Pq Vt str
-If not set to
-.Dq Li NO ,
-this is the faith prefix to enable a FAITH IPv6-to-IPv4 TCP
-translator.
-You also need
-.Xr faithd 8
-setup.
.It Va ipv6_ipv4mapping
.Pq Vt bool
If set to
device tun # Packet tunnel.
device md # Memory "disks"
device gif # IPv6 and IPv4 tunneling
-device faith # IPv6-to-IPv4 relaying (translation)
device firmware # firmware assist module
# The `bpf' device enables the Berkeley Packet Filter.
device tun # Packet tunnel.
device md # Memory "disks"
device gif # IPv6 and IPv4 tunneling
-device faith # IPv6-to-IPv4 relaying (translation)
#device firmware # firmware assist module
# SCSI peripherals
# Misc pseudo devices
device bpf # Required for DHCP
-device faith # IPv6-to-IPv4 relaying (translation)
device firmware # firmware(9) required for USB wlan
device gif # IPv6 and IPv4 tunneling
device loop # Network loopback
# Misc pseudo devices
device bpf # Required for DHCP
-device faith # IPv6-to-IPv4 relaying (translation)
device firmware # firmware(9) required for USB wlan
device gif # IPv6 and IPv4 tunneling
device loop # Network loopback
#device tun # Packet tunnel.
#device md # Memory "disks"
#device gif # IPv6 and IPv4 tunneling
-#device faith # IPv6-to-IPv4 relaying (translation)
#device firmware # firmware assist module
# Serial (COM) ports
#device tun # Packet tunnel.
#device md # Memory "disks"
#device gif # IPv6 and IPv4 tunneling
-#device faith # IPv6-to-IPv4 relaying (translation)
#device firmware # firmware assist module
# SCSI peripherals
#device tun # Packet tunnel.
device md # Memory "disks"
#device gif # IPv6 and IPv4 tunneling
-#device faith # IPv6-to-IPv4 relaying (translation)
#device firmware # firmware assist module
# Ethernet
device tun # Packet tunnel.
device md # Memory "disks"
#device gif # IPv6 and IPv4 tunneling
-#device faith # IPv6-to-IPv4 relaying (translation)
#device firmware # firmware assist module
device ether # Ethernet support
device miibus # Required for ethernet
#device tun # Packet tunnel.
#device md # Memory "disks"
#device gif # IPv6 and IPv4 tunneling
-#device faith # IPv6-to-IPv4 relaying (translation)
#device firmware # firmware assist module
# SCSI peripherals
if_ef_load="NO" # pseudo-device providing support for multiple
# ethernet frame types
if_epair_load="NO" # Virtual b-t-b Ethernet-like interface pair
-if_faith_load="NO" # IPv6-to-IPv4 TCP relay capturing interface
if_gif_load="NO" # generic tunnel interface
if_gre_load="NO" # encapsulating network device
if_stf_load="NO" # 6to4 tunnel interface
device me
options XBONEHACK
-# The `faith' device captures packets sent to it and diverts them
-# to the IPv4/IPv6 translation daemon.
# The `stf' device implements 6to4 encapsulation.
-device faith
device stf
# The pf packet filter consists of three devices:
net/if_enc.c optional enc ipsec inet | enc ipsec inet6
net/if_epair.c optional epair
net/if_ethersubr.c optional ether
-net/if_faith.c optional faith
net/if_fddisubr.c optional fddi
net/if_fwsubr.c optional fwip
net/if_gif.c optional gif inet | gif inet6 | \
device tun # Packet tunnel.
device md # Memory "disks"
device gif # IPv6 and IPv4 tunneling
-device faith # IPv6-to-IPv4 relaying (translation)
device firmware # firmware assist module
# The `bpf' device enables the Berkeley Packet Filter.
#device tun # Packet tunnel.
#device md # Memory "disks"
#device gif # IPv6 and IPv4 tunneling
-#device faith # IPv6-to-IPv4 relaying (translation)
# The `bpf' device enables the Berkeley Packet Filter.
# Be aware of the administrative consequences of enabling this!
device tun # Packet tunnel.
device md # Memory "disks"
device gif # IPv6 and IPv4 tunneling
-device faith # IPv6-to-IPv4 relaying (translation)
# Wireless cards
options IEEE80211_SUPPORT_MESH
device tun # Packet tunnel.
device md # Memory "disks"
device gif # IPv6 and IPv4 tunneling
-device faith # IPv6-to-IPv4 relaying (translation)
# The `bpf' device enables the Berkeley Packet Filter.
# Be aware of the administrative consequences of enabling this!
device tun # Packet tunnel.
device md # Memory "disks"
device gif # IPv6 and IPv4 tunneling
-device faith # IPv6-to-IPv4 relaying (translation)
# The `bpf' device enables the Berkeley Packet Filter.
# Be aware of the administrative consequences of enabling this!
device tun # Packet tunnel.
device md # Memory "disks"
device gif # IPv6 and IPv4 tunneling
-device faith # IPv6-to-IPv4 relaying (translation)
device firmware # firmware assist module
# The `bpf' device enables the Berkeley Packet Filter.
./etc/rc.d/dmesg
./etc/rc.d/dumpon
./etc/rc.d/encswap
-./etc/rc.d/faith
./etc/rc.d/fsck
./etc/rc.d/ftp-proxy
./etc/rc.d/ftpd
if_disc \
if_edsc \
if_epair \
- if_faith \
${_if_gif} \
${_if_gre} \
${_if_me} \
+++ /dev/null
-# $FreeBSD$
-
-.PATH: ${.CURDIR}/../../net
-
-KMOD= if_faith
-SRCS= if_faith.c opt_inet.h opt_inet6.h
-
-.include <bsd.kmod.mk>
+++ /dev/null
-/* $KAME: if_faith.c,v 1.23 2001/12/17 13:55:29 sumikawa Exp $ */
-
-/*-
- * Copyright (c) 1982, 1986, 1993
- * The Regents of the University of California. 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.
- * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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$
- */
-/*
- * derived from
- * @(#)if_loop.c 8.1 (Berkeley) 6/10/93
- * Id: if_loop.c,v 1.22 1996/06/19 16:24:10 wollman Exp
- */
-
-/*
- * Loopback interface driver for protocol testing and timing.
- */
-#include "opt_inet.h"
-#include "opt_inet6.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/mbuf.h>
-#include <sys/module.h>
-#include <sys/socket.h>
-#include <sys/errno.h>
-#include <sys/sockio.h>
-#include <sys/time.h>
-#include <sys/queue.h>
-#include <sys/types.h>
-#include <sys/malloc.h>
-
-#include <net/if.h>
-#include <net/if_var.h>
-#include <net/if_clone.h>
-#include <net/if_types.h>
-#include <net/netisr.h>
-#include <net/route.h>
-#include <net/bpf.h>
-#include <net/vnet.h>
-
-#ifdef INET
-#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/in_var.h>
-#include <netinet/ip.h>
-#endif
-
-#ifdef INET6
-#ifndef INET
-#include <netinet/in.h>
-#endif
-#include <netinet6/in6_var.h>
-#include <netinet/ip6.h>
-#include <netinet6/ip6_var.h>
-#endif
-
-struct faith_softc {
- struct ifnet *sc_ifp;
-};
-
-static int faithioctl(struct ifnet *, u_long, caddr_t);
-static int faithoutput(struct ifnet *, struct mbuf *, const struct sockaddr *,
- struct route *);
-#ifdef INET6
-static int faithprefix(struct in6_addr *);
-#endif
-
-static int faithmodevent(module_t, int, void *);
-
-static const char faithname[] = "faith";
-static MALLOC_DEFINE(M_FAITH, faithname, "Firewall Assisted Tunnel Interface");
-
-static int faith_clone_create(struct if_clone *, int, caddr_t);
-static void faith_clone_destroy(struct ifnet *);
-static struct if_clone *faith_cloner;
-
-#define FAITHMTU 1500
-
-static int
-faithmodevent(mod, type, data)
- module_t mod;
- int type;
- void *data;
-{
-
- switch (type) {
- case MOD_LOAD:
- faith_cloner = if_clone_simple(faithname, faith_clone_create,
- faith_clone_destroy, 0);
-#ifdef INET6
- faithprefix_p = faithprefix;
-#endif
-
- break;
- case MOD_UNLOAD:
-#ifdef INET6
- faithprefix_p = NULL;
-#endif
-
- if_clone_detach(faith_cloner);
- break;
- default:
- return EOPNOTSUPP;
- }
- return 0;
-}
-
-static moduledata_t faith_mod = {
- "if_faith",
- faithmodevent,
- 0
-};
-
-DECLARE_MODULE(if_faith, faith_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
-MODULE_VERSION(if_faith, 1);
-
-static int
-faith_clone_create(ifc, unit, params)
- struct if_clone *ifc;
- int unit;
- caddr_t params;
-{
- struct ifnet *ifp;
- struct faith_softc *sc;
-
- sc = malloc(sizeof(struct faith_softc), M_FAITH, M_WAITOK | M_ZERO);
- ifp = sc->sc_ifp = if_alloc(IFT_FAITH);
- if (ifp == NULL) {
- free(sc, M_FAITH);
- return (ENOSPC);
- }
-
- ifp->if_softc = sc;
- if_initname(sc->sc_ifp, faithname, unit);
-
- ifp->if_mtu = FAITHMTU;
- /* Change to BROADCAST experimentaly to announce its prefix. */
- ifp->if_flags = /* IFF_LOOPBACK */ IFF_BROADCAST | IFF_MULTICAST;
- ifp->if_ioctl = faithioctl;
- ifp->if_output = faithoutput;
- ifp->if_hdrlen = 0;
- ifp->if_addrlen = 0;
- ifp->if_snd.ifq_maxlen = ifqmaxlen;
- if_attach(ifp);
- bpfattach(ifp, DLT_NULL, sizeof(u_int32_t));
- return (0);
-}
-
-static void
-faith_clone_destroy(ifp)
- struct ifnet *ifp;
-{
- struct faith_softc *sc = ifp->if_softc;
-
- bpfdetach(ifp);
- if_detach(ifp);
- if_free(ifp);
- free(sc, M_FAITH);
-}
-
-static int
-faithoutput(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
- struct route *ro)
-{
- int isr;
- u_int32_t af;
- struct rtentry *rt = NULL;
-
- M_ASSERTPKTHDR(m);
-
- if (ro != NULL)
- rt = ro->ro_rt;
- /* BPF writes need to be handled specially. */
- if (dst->sa_family == AF_UNSPEC)
- bcopy(dst->sa_data, &af, sizeof(af));
- else
- af = dst->sa_family;
-
- if (bpf_peers_present(ifp->if_bpf))
- bpf_mtap2(ifp->if_bpf, &af, sizeof(af), m);
-
- if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) {
- m_freem(m);
- return (rt->rt_flags & RTF_BLACKHOLE ? 0 :
- rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH);
- }
- if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
- if_inc_counter(ifp, IFCOUNTER_OBYTES, m->m_pkthdr.len);
- switch (af) {
-#ifdef INET
- case AF_INET:
- isr = NETISR_IP;
- break;
-#endif
-#ifdef INET6
- case AF_INET6:
- isr = NETISR_IPV6;
- break;
-#endif
- default:
- m_freem(m);
- return EAFNOSUPPORT;
- }
-
- /* XXX do we need more sanity checks? */
-
- m->m_pkthdr.rcvif = ifp;
- if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
- if_inc_counter(ifp, IFCOUNTER_IBYTES, m->m_pkthdr.len);
- netisr_dispatch(isr, m);
- return (0);
-}
-
-/*
- * Process an ioctl request.
- */
-/* ARGSUSED */
-static int
-faithioctl(ifp, cmd, data)
- struct ifnet *ifp;
- u_long cmd;
- caddr_t data;
-{
- struct ifreq *ifr = (struct ifreq *)data;
- int error = 0;
-
- switch (cmd) {
-
- case SIOCSIFADDR:
- ifp->if_flags |= IFF_UP;
- ifp->if_drv_flags |= IFF_DRV_RUNNING;
-
- /*
- * Everything else is done at a higher level.
- */
- break;
-
- case SIOCADDMULTI:
- case SIOCDELMULTI:
- if (ifr == 0) {
- error = EAFNOSUPPORT; /* XXX */
- break;
- }
- switch (ifr->ifr_addr.sa_family) {
-#ifdef INET
- case AF_INET:
- break;
-#endif
-#ifdef INET6
- case AF_INET6:
- break;
-#endif
-
- default:
- error = EAFNOSUPPORT;
- break;
- }
- break;
-
-#ifdef SIOCSIFMTU
- case SIOCSIFMTU:
- ifp->if_mtu = ifr->ifr_mtu;
- break;
-#endif
-
- case SIOCSIFFLAGS:
- break;
-
- default:
- error = EINVAL;
- }
- return (error);
-}
-
-#ifdef INET6
-/*
- * XXX could be slow
- * XXX could be layer violation to call sys/net from sys/netinet6
- */
-static int
-faithprefix(in6)
- struct in6_addr *in6;
-{
- struct rtentry *rt;
- struct sockaddr_in6 sin6;
- int ret;
-
- if (V_ip6_keepfaith == 0)
- return 0;
-
- bzero(&sin6, sizeof(sin6));
- sin6.sin6_family = AF_INET6;
- sin6.sin6_len = sizeof(struct sockaddr_in6);
- sin6.sin6_addr = *in6;
- rt = in6_rtalloc1((struct sockaddr *)&sin6, 0, 0UL, RT_DEFAULT_FIB);
- if (rt && rt->rt_ifp && rt->rt_ifp->if_type == IFT_FAITH &&
- (rt->rt_ifp->if_flags & IFF_UP) != 0)
- ret = 1;
- else
- ret = 0;
- if (rt)
- RTFREE_LOCKED(rt);
- return ret;
-}
-#endif
/* not based on IANA assignments */
#define IFT_GIF 0xf0
#define IFT_PVC 0xf1
-#define IFT_FAITH 0xf2
#define IFT_ENC 0xf4
#define IFT_PFLOG 0xf6
#define IFT_PFSYNC 0xf7
#define IP_RECVIF 20 /* bool; receive reception if w/dgram */
/* for IPSEC */
#define IP_IPSEC_POLICY 21 /* int; set/get security policy */
-#define IP_FAITH 22 /* bool; accept FAITH'ed connections */
-
+ /* unused; was IP_FAITH */
#define IP_ONESBCAST 23 /* bool: send all-ones broadcast */
#define IP_BINDANY 24 /* bool: allow bind to any address */
#define IP_BINDMULTI 25 /* bool: allow multiple listeners on a tuple */
#define IPCTL_STATS 12 /* ipstat structure */
#define IPCTL_ACCEPTSOURCEROUTE 13 /* may accept source routed packets */
#define IPCTL_FASTFORWARDING 14 /* use fast IP forwarding code */
-#define IPCTL_KEEPFAITH 15 /* FAITH IPv4->IPv6 translater ctl */
+ /* 15, unused, was: IPCTL_KEEPFAITH */
#define IPCTL_GIF_TTL 16 /* default TTL for gif encap packet */
#endif /* __BSD_VISIBLE */
inp->inp_lport != lport)
continue;
- /* XXX inp locking */
- if (ifp && ifp->if_type == IFT_FAITH &&
- (inp->inp_flags & INP_FAITH) == 0)
- continue;
-
injail = prison_flag(inp->inp_cred, PR_IP4);
if (injail) {
if (prison_check_ip4(inp->inp_cred,
inp->inp_lport != lport)
continue;
- /* XXX inp locking */
- if (ifp && ifp->if_type == IFT_FAITH &&
- (inp->inp_flags & INP_FAITH) == 0)
- continue;
-
injail = prison_flag(inp->inp_cred, PR_IP4);
if (injail) {
if (prison_check_ip4(inp->inp_cred,
inp->inp_lport != lport)
continue;
- /* XXX inp locking */
- if (ifp && ifp->if_type == IFT_FAITH &&
- (inp->inp_flags & INP_FAITH) == 0)
- continue;
-
injail = prison_flag(inp->inp_cred, PR_IP4);
if (injail) {
if (prison_check_ip4(inp->inp_cred,
db_printf("%sINP_MTUDISC", comma ? ", " : "");
comma = 1;
}
- if (inp_flags & INP_FAITH) {
- db_printf("%sINP_FAITH", comma ? ", " : "");
- comma = 1;
- }
if (inp_flags & INP_RECVTTL) {
db_printf("%sINP_RECVTTL", comma ? ", " : "");
comma = 1;
#define INP_ANONPORT 0x00000040 /* port chosen for user */
#define INP_RECVIF 0x00000080 /* receive incoming interface */
#define INP_MTUDISC 0x00000100 /* user can do MTU discovery */
-#define INP_FAITH 0x00000200 /* accept FAITH'ed connections */
+ /* 0x000200 unused: was INP_FAITH */
#define INP_RECVTTL 0x00000400 /* receive incoming IP TTL */
#define INP_DONTFRAG 0x00000800 /* don't fragment packet */
#define INP_BINDANY 0x00001000 /* allow bind to any address */
m->m_len += hlen;
m->m_data -= hlen;
- if (m->m_pkthdr.rcvif && m->m_pkthdr.rcvif->if_type == IFT_FAITH) {
- /*
- * Deliver very specific ICMP type only.
- */
- switch (icp->icmp_type) {
- case ICMP_UNREACH:
- case ICMP_TIMXCEED:
- break;
- default:
- goto freeit;
- }
- }
-
#ifdef ICMPPRINTFS
if (icmpprintfs)
printf("icmp_input, type %d code %d\n", icp->icmp_type,
&VNET_NAME(ipsendredirects), 0,
"Enable sending IP redirects");
-static VNET_DEFINE(int, ip_keepfaith);
-#define V_ip_keepfaith VNET(ip_keepfaith)
-SYSCTL_INT(_net_inet_ip, IPCTL_KEEPFAITH, keepfaith, CTLFLAG_VNET | CTLFLAG_RW,
- &VNET_NAME(ip_keepfaith), 0,
- "Enable packet capture for FAITH IPv4->IPv6 translater daemon");
-
static VNET_DEFINE(int, ip_sendsourcequench);
#define V_ip_sendsourcequench VNET(ip_sendsourcequench)
SYSCTL_INT(_net_inet_ip, OID_AUTO, sendsourcequench, CTLFLAG_VNET | CTLFLAG_RW,
if (ip->ip_dst.s_addr == INADDR_ANY)
goto ours;
- /*
- * FAITH(Firewall Aided Internet Translator)
- */
- if (ifp && ifp->if_type == IFT_FAITH) {
- if (V_ip_keepfaith) {
- if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_ICMP)
- goto ours;
- }
- m_freem(m);
- return;
- }
-
/*
* Not for us; forward if possible and desirable.
*/
case IP_RECVDSTADDR:
case IP_RECVTTL:
case IP_RECVIF:
- case IP_FAITH:
case IP_ONESBCAST:
case IP_DONTFRAG:
case IP_RECVTOS:
OPTSET(INP_RECVIF);
break;
- case IP_FAITH:
- OPTSET(INP_FAITH);
- break;
-
case IP_ONESBCAST:
OPTSET(INP_ONESBCAST);
break;
case IP_RECVTTL:
case IP_RECVIF:
case IP_PORTRANGE:
- case IP_FAITH:
case IP_ONESBCAST:
case IP_DONTFRAG:
case IP_BINDANY:
optval = 0;
break;
- case IP_FAITH:
- optval = OPTBIT(INP_FAITH);
- break;
-
case IP_ONESBCAST:
optval = OPTBIT(INP_ONESBCAST);
break;
goto freeit;
}
- if (faithprefix_p != NULL && (*faithprefix_p)(&ip6->ip6_dst)) {
- /*
- * Deliver very specific ICMP6 type only.
- * This is important to deliver TOOBIG. Otherwise PMTUD
- * will not work.
- */
- switch (icmp6->icmp6_type) {
- case ICMP6_DST_UNREACH:
- case ICMP6_PACKET_TOO_BIG:
- case ICMP6_TIME_EXCEEDED:
- break;
- default:
- goto freeit;
- }
- }
-
ICMP6STAT_INC(icp6s_inhist[icmp6->icmp6_type]);
icmp6_ifstat_inc(ifp, ifs6_in_msg);
if (icmp6->icmp6_type < ICMP6_INFOMSG_MASK)
struct in6_aliasreq *, int);
static void in6_unlink_ifa(struct in6_ifaddr *, struct ifnet *);
-int (*faithprefix_p)(struct in6_addr *);
-
static int in6_validate_ifra(struct ifnet *, struct in6_aliasreq *,
struct in6_ifaddr *, int);
static struct in6_ifaddr *in6_alloc_ifa(struct ifnet *,
if (ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED)
return (0);
- switch (ifp->if_type) {
-#ifdef IFT_DUMMY
- case IFT_DUMMY:
-#endif
- case IFT_FAITH:
- /*
- * These interfaces do not have the IFF_LOOPBACK flag,
- * but loop packets back. We do not have to do DAD on such
- * interfaces. We should even omit it, because loop-backed
- * NS would confuse the DAD procedure.
- */
+ /*
+ * Our DAD routine requires the interface up and running.
+ * However, some interfaces can be up before the RUNNING
+ * status. Additionaly, users may try to assign addresses
+ * before the interface becomes up (or running).
+ * We simply skip DAD in such a case as a work around.
+ * XXX: we should rather mark "tentative" on such addresses,
+ * and do DAD after the interface becomes ready.
+ */
+ if (!((ifp->if_flags & IFF_UP) &&
+ (ifp->if_drv_flags & IFF_DRV_RUNNING)))
return (0);
- default:
- /*
- * Our DAD routine requires the interface up and running.
- * However, some interfaces can be up before the RUNNING
- * status. Additionaly, users may try to assign addresses
- * before the interface becomes up (or running).
- * We simply skip DAD in such a case as a work around.
- * XXX: we should rather mark "tentative" on such addresses,
- * and do DAD after the interface becomes ready.
- */
- if (!((ifp->if_flags & IFF_UP) &&
- (ifp->if_drv_flags & IFF_DRV_RUNNING)))
- return (0);
- return (1);
- }
+ return (1);
}
/*
#define IPV6_IPSEC_POLICY 28 /* struct; get/set security policy */
#endif /* IPSEC */
-#define IPV6_FAITH 29 /* bool; accept FAITH'ed connections */
-
+ /* 29; unused; was IPV6_FAITH */
#if 1 /* IPV6FIREWALL */
#define IPV6_FW_ADD 30 /* add a firewall rule to chain */
#define IPV6_FW_DEL 31 /* delete a firewall rule from chain */
#define IPV6CTL_SOURCECHECK 10 /* verify source route and intf */
#define IPV6CTL_SOURCECHECK_LOGINT 11 /* minimume logging interval */
#define IPV6CTL_ACCEPT_RTADV 12
-#define IPV6CTL_KEEPFAITH 13
+ /* 13; unused; was: IPV6CTL_KEEPFAITH */
#define IPV6CTL_LOG_INTERVAL 14
#define IPV6CTL_HDRNESTLIMIT 15
#define IPV6CTL_DAD_COUNT 16
#define sin6tosa(sin6) ((struct sockaddr *)(sin6))
#define ifatoia6(ifa) ((struct in6_ifaddr *)(ifa))
-extern int (*faithprefix_p)(struct in6_addr *);
#endif /* _KERNEL */
#ifndef _SIZE_T_DECLARED
struct inpcbhead *head;
struct inpcb *inp, *tmpinp;
u_short fport = fport_arg, lport = lport_arg;
- int faith;
-
- if (faithprefix_p != NULL)
- faith = (*faithprefix_p)(laddr);
- else
- faith = 0;
/*
* First look for an exact match.
continue;
}
- /* XXX inp locking */
- if (faith && (inp->inp_flags & INP_FAITH) == 0)
- continue;
-
injail = prison_flag(inp->inp_cred, PR_IP6);
if (injail) {
if (prison_check_ip6(inp->inp_cred,
continue;
}
- /* XXX inp locking */
- if (faith && (inp->inp_flags & INP_FAITH) == 0)
- continue;
-
injail = prison_flag(inp->inp_cred, PR_IP6);
if (injail) {
if (prison_check_ip6(inp->inp_cred,
struct inpcbhead *head;
struct inpcb *inp, *tmpinp;
u_short fport = fport_arg, lport = lport_arg;
- int faith;
KASSERT((lookupflags & ~(INPLOOKUP_WILDCARD)) == 0,
("%s: invalid lookup flags %d", __func__, lookupflags));
INP_HASH_LOCK_ASSERT(pcbinfo);
- if (faithprefix_p != NULL)
- faith = (*faithprefix_p)(laddr);
- else
- faith = 0;
-
/*
* First look for an exact match.
*/
continue;
}
- /* XXX inp locking */
- if (faith && (inp->inp_flags & INP_FAITH) == 0)
- continue;
-
injail = prison_flag(inp->inp_cred, PR_IP6);
if (injail) {
if (prison_check_ip6(inp->inp_cred,
VNET_DEFINE(int, ip6_mcast_pmtu) = 0; /* enable pMTU discovery for multicast? */
VNET_DEFINE(int, ip6_v6only) = 1;
-VNET_DEFINE(int, ip6_keepfaith) = 0;
VNET_DEFINE(time_t, ip6_log_time) = (time_t)0L;
#ifdef IPSTEALTH
VNET_DEFINE(int, ip6stealth) = 0;
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip6_rfc6204w3), 0,
"Accept the default router list from ICMPv6 RA messages even "
"when packet forwarding enabled.");
-SYSCTL_INT(_net_inet6_ip6, IPV6CTL_KEEPFAITH, keepfaith,
- CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip6_keepfaith), 0, "");
SYSCTL_INT(_net_inet6_ip6, IPV6CTL_LOG_INTERVAL, log_interval,
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip6_log_interval), 0, "");
SYSCTL_INT(_net_inet6_ip6, IPV6CTL_HDRNESTLIMIT, hdrnestlimit,
/* FALLTHROUGH */
case IPV6_UNICAST_HOPS:
case IPV6_HOPLIMIT:
- case IPV6_FAITH:
case IPV6_RECVPKTINFO:
case IPV6_RECVHOPLIMIT:
OPTSET(IN6P_RTHDR);
break;
- case IPV6_FAITH:
- OPTSET(INP_FAITH);
- break;
-
case IPV6_RECVPATHMTU:
/*
* We ignore this option for TCP
case IPV6_RECVRTHDR:
case IPV6_RECVPATHMTU:
- case IPV6_FAITH:
case IPV6_V6ONLY:
case IPV6_PORTRANGE:
case IPV6_RECVTCLASS:
optval = OPTBIT(IN6P_MTU);
break;
- case IPV6_FAITH:
- optval = OPTBIT(INP_FAITH);
- break;
-
case IPV6_V6ONLY:
optval = OPTBIT(IN6P_IPV6_V6ONLY);
break;
* receiving IF. */
VNET_DECLARE(int, ip6_rfc6204w3); /* Accept defroute from RA even when
forwarding enabled */
-VNET_DECLARE(int, ip6_keepfaith); /* Firewall Aided Internet Translator */
VNET_DECLARE(int, ip6_log_interval);
VNET_DECLARE(time_t, ip6_log_time);
VNET_DECLARE(int, ip6_hdrnestlimit); /* upper limit of # of extension
#define V_ip6_no_radr VNET(ip6_no_radr)
#define V_ip6_norbit_raif VNET(ip6_norbit_raif)
#define V_ip6_rfc6204w3 VNET(ip6_rfc6204w3)
-#define V_ip6_keepfaith VNET(ip6_keepfaith)
#define V_ip6_log_interval VNET(ip6_log_interval)
#define V_ip6_log_time VNET(ip6_log_time)
#define V_ip6_hdrnestlimit VNET(ip6_hdrnestlimit)
RIP6STAT_INC(rip6s_ipackets);
- if (faithprefix_p != NULL && (*faithprefix_p)(&ip6->ip6_dst)) {
- /* XXX Send icmp6 host/port unreach? */
- m_freem(m);
- return (IPPROTO_DONE);
- }
-
init_sin6(&fromsa, m); /* general init */
ifp = m->m_pkthdr.rcvif;
if (in6_setscope(&dst.sin6_addr, m->m_pkthdr.rcvif, NULL) != 0) {
goto out;
}
- if (faithprefix_p != NULL && (*faithprefix_p) (&dst.sin6_addr)) {
- /* XXX send icmp6 host/port unreach? */
- goto out;
- }
length = ntohs(ip6->ip6_plen) + iphlen;
/* Validate mbuf chain length with IP payload length. */
if (SCTP_HEADER_LEN(m) != length) {
ifp = m->m_pkthdr.rcvif;
ip6 = mtod(m, struct ip6_hdr *);
- if (faithprefix_p != NULL && (*faithprefix_p)(&ip6->ip6_dst)) {
- /* XXX send icmp6 host/port unreach? */
- m_freem(m);
- return (IPPROTO_DONE);
- }
-
#ifndef PULLDOWN_TEST
IP6_EXTHDR_CHECK(m, off, sizeof(struct udphdr), IPPROTO_DONE);
ip6 = mtod(m, struct ip6_hdr *);
device tun # Packet tunnel.
device md # Memory "disks"
device gif # IPv6 and IPv4 tunneling
-device faith # IPv6-to-IPv4 relaying (translation)
device firmware # firmware assist module
# The `bpf' device enables the Berkeley Packet Filter.
device md # Memory "disks"
device ofwd # Open Firmware disks
device gif # IPv6 and IPv4 tunneling
-device faith # IPv6-to-IPv4 relaying/(translation)
device firmware # firmware assist module
# The `bpf' device enables the Berkeley Packet Filter.
device md # Memory "disks"
device ofwd # Open Firmware disks
device gif # IPv6 and IPv4 tunneling
-device faith # IPv6-to-IPv4 relaying/(translation)
device firmware # firmware assist module
# The `bpf' device enables the Berkeley Packet Filter.
device tun # Packet tunnel.
device md # Memory "disks"
device gif # IPv6 and IPv4 tunneling
-device faith # IPv6-to-IPv4 relaying/(translation)
device firmware # firmware assist module
device tun # Packet tunnel.
device md # Memory "disks"
device gif # IPv6 and IPv4 tunneling
-device faith # IPv6-to-IPv4 relaying (translation)
device firmware # firmware assist module
# The `bpf' device enables the Berkeley Packet Filter.
.if ${MK_INET6} == no
OLD_FILES+=sbin/ping6
OLD_FILES+=sbin/rtsol
-OLD_FILES+=usr/sbin/faithd
OLD_FILES+=usr/sbin/ip6addrctl
OLD_FILES+=usr/sbin/mld6query
OLD_FILES+=usr/sbin/ndp
device pty
device md
device gif
-device faith
device firmware
device bpf
device uhci
device pty
device md
device gif
-device faith
device firmware
device bpf
device uhci
---
net.inet.ip.intr_queue_maxlen
----
-net.inet.ip.keepfaith
-bool
-
-This is used in conjunction with
-.Xr faithd 8
-to control the FAITH IPv6/v4 translator daemon.
-
---
net.inet.ip.maxfragpackets
device pty # Pseudo-ttys (telnet etc)
device md # Memory "disks"
device gif # IPv6 and IPv4 tunneling
-device faith # IPv6-to-IPv4 relaying (translation)
# The `bpf' device enables the Berkeley Packet Filter.
# Be aware of the administrative consequences of enabling this!
device pty # Pseudo-ttys (telnet etc)
device md # Memory "disks"
device gif # IPv6 and IPv4 tunneling
-device faith # IPv6-to-IPv4 relaying (translation)
# The `bpf' device enables the Berkeley Packet Filter.
# Be aware of the administrative consequences of enabling this!
device pty # Pseudo-ttys (telnet etc)
device md # Memory "disks"
device gif # IPv6 and IPv4 tunneling
-device faith # IPv6-to-IPv4 relaying (translation)
# The `bpf' device enables the Berkeley Packet Filter.
# Be aware of the administrative consequences of enabling this!
.endif
.if ${MK_INET6} != "no"
-SUBDIR+= faithd
SUBDIR+= ip6addrctl
SUBDIR+= mld6query
SUBDIR+= ndp
f_struct "$dev" get name if || continue
# Skip unsavory interfaces
case "$if" in
- lo[0-9]*|ppp[0-9]*|sl[0-9]*|faith[0-9]*) continue ;;
+ lo[0-9]*|ppp[0-9]*|sl[0-9]*) continue ;;
esac
iflist="$iflist $if"
done
+++ /dev/null
-# 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>
+++ /dev/null
-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
+++ /dev/null
-.\" $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.
+++ /dev/null
-/* $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);
-}
+++ /dev/null
-/* $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*/
+++ /dev/null
-/* $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 */
-}
+++ /dev/null
-/* $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;
-}
+++ /dev/null
-/* $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 *);
+++ /dev/null
-/* $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 */
- }
-}
+++ /dev/null
-# 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
* or name a tcpmux service
* or specify a unix domain socket
* socket type stream/dgram/raw/rdm/seqpacket
- * protocol tcp[4][6][/faith], udp[4][6], unix
+ * protocol tcp[4][6], udp[4][6], unix
* wait/nowait single-threaded/multi-threaded
* user[:group][/login-class] user/group/login-class to run daemon as
* server program full path name
syslog(LOG_ERR, "setsockopt (IPV6_V6ONLY): %m");
}
#undef turnon
-#ifdef IPV6_FAITH
- if (sep->se_type == FAITH_TYPE) {
- if (setsockopt(sep->se_fd, IPPROTO_IPV6, IPV6_FAITH, &on,
- sizeof(on)) < 0) {
- syslog(LOG_ERR, "setsockopt (IPV6_FAITH): %m");
- }
- }
-#endif
#ifdef IPSEC
ipsecsetup(sep);
#endif
arg = sskip(&cp);
if (strncmp(arg, "tcp", 3) == 0) {
sep->se_proto = newstr(strsep(&arg, "/"));
- if (arg != NULL) {
- if (strcmp(arg, "faith") == 0)
- sep->se_type = FAITH_TYPE;
+ if (arg != NULL && (strcmp(arg, "faith") == 0)) {
+ syslog(LOG_ERR, "faith has been deprecated");
+ goto more;
}
} else {
if (sep->se_type == NORM_TYPE &&
strncmp(arg, "faith/", 6) == 0) {
- arg += 6;
- sep->se_type = FAITH_TYPE;
+ syslog(LOG_ERR, "faith has been deprecated");
+ goto more;
}
sep->se_proto = newstr(arg);
}