Renove faith(4) and faithd(8) from base. It looks like industry

have chosen different (and more traditional) stateless/statuful
NAT64 as translation mechanism. Last non-trivial commits to both
faith(4) and faithd(8) happened more than 12 years ago, so I assume
it is time to drop RFC3142 in FreeBSD.

No objections from:	net@
This commit is contained in:
Alexander V. Chernikov 2014-11-09 21:33:01 +00:00
parent 48a9d8f214
commit 603eaf792b
83 changed files with 39 additions and 4537 deletions

View File

@ -38,6 +38,12 @@
# 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

View File

@ -31,6 +31,10 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 11.x IS SLOW:
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

View File

@ -514,9 +514,6 @@ stf_interface_ipv4plen="0" # Prefix length for 6to4 IPv4 addr,
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,

View File

@ -372,7 +372,6 @@ dhcpif()
case $1 in
lo[0-9]*|\
stf[0-9]*|\
faith[0-9]*|\
lp[0-9]*|\
sl[0-9]*)
return 1
@ -591,7 +590,6 @@ ipv6_autoconfif()
case $_if in
lo[0-9]*|\
stf[0-9]*|\
faith[0-9]*|\
lp[0-9]*|\
sl[0-9]*)
return 1

View File

@ -42,7 +42,6 @@ FILES= DAEMON \
dhclient \
dmesg \
dumpon \
faith \
fsck \
ftpd \
gbde \

View File

@ -4,7 +4,7 @@
#
# 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

View File

@ -26,7 +26,7 @@
#
# PROVIDE: bridge
# REQUIRE: netif faith ppp stf
# REQUIRE: netif ppp stf
# KEYWORD: nojail
. /etc/rc.subr

View File

@ -6,7 +6,7 @@
#
# PROVIDE: defaultroute
# REQUIRE: devd faith netif stf
# REQUIRE: devd netif stf
# KEYWORD: nojail
. /etc/rc.subr

View File

@ -1,75 +0,0 @@
#!/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"

View File

@ -6,7 +6,7 @@
#
# PROVIDE: routing
# REQUIRE: faith netif ppp stf
# REQUIRE: netif ppp stf
# KEYWORD: nojailvnet
. /etc/rc.subr
@ -245,7 +245,7 @@ static_inet6()
[Nn][Oo][Nn][Ee])
return
;;
lo0|faith[0-9]*)
lo0)
continue
;;
esac

View File

@ -30,8 +30,6 @@
*/
/*
* "#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
@ -101,10 +99,6 @@ __FBSDID("$FreeBSD$");
#include "nscache.h"
#endif
#if defined(__KAME__) && defined(INET6)
# define FAITH
#endif
#define ANY 0
#define YES 1
#define NO 0
@ -1316,47 +1310,6 @@ get_ai(const struct addrinfo *pai, const struct afd *afd, const char *addr)
{
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));
@ -1370,11 +1323,6 @@ get_ai(const struct addrinfo *pai, const struct afd *afd, const char *addr)
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;
}

View File

@ -414,7 +414,6 @@ getnameinfo_link(const struct sockaddr *sa, socklen_t salen,
/*
* 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)

View File

@ -109,7 +109,6 @@ device tun # Packet tunnel.
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

View File

@ -114,7 +114,6 @@ device tun # Packet tunnel.
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

View File

@ -132,7 +132,6 @@ MAN= aac.4 \
et.4 \
eventtimers.4 \
exca.4 \
faith.4 \
fatm.4 \
fd.4 \
fdc.4 \
@ -637,7 +636,6 @@ MLINKS+=en.4 if_en.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 \

View File

@ -1,133 +0,0 @@
.\" $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.

View File

@ -241,17 +241,6 @@ Defaults to off.
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

View File

@ -393,10 +393,6 @@ For wildcard sockets, this can restrict connections to IPv6 only.
.\".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

View File

@ -2948,15 +2948,6 @@ This can be set to
.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

View File

@ -310,7 +310,6 @@ device vlan # 802.1Q VLAN support
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.

View File

@ -143,7 +143,6 @@ device vlan # 802.1Q VLAN support
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

View File

@ -54,7 +54,6 @@ options FDT_DTB_STATIC
# 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

View File

@ -57,7 +57,6 @@ options FDT_DTB_STATIC
# 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

View File

@ -104,7 +104,6 @@ device ether # Ethernet support
#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

View File

@ -136,7 +136,6 @@ device ether # Ethernet support
#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

View File

@ -92,7 +92,6 @@ device ether # Ethernet support
#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

View File

@ -75,7 +75,6 @@ device vlan # 802.1Q VLAN support
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

View File

@ -146,7 +146,6 @@ device ether # Ethernet support
#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

View File

@ -254,7 +254,6 @@ if_disc_load="NO" # Discard device
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

View File

@ -890,10 +890,7 @@ device gre
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:

View File

@ -3229,7 +3229,6 @@ net/if_edsc.c optional edsc
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 | \

View File

@ -318,7 +318,6 @@ device vlan # 802.1Q VLAN support
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.

View File

@ -66,7 +66,6 @@ device ether # Ethernet support
#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!

View File

@ -82,7 +82,6 @@ device ether # Ethernet support
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

View File

@ -55,7 +55,6 @@ device ether # Ethernet support
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!

View File

@ -53,7 +53,6 @@ device ether # Ethernet support
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!

View File

@ -261,7 +261,6 @@ device vlan # 802.1Q VLAN support
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.

View File

@ -197,7 +197,6 @@
./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

View File

@ -145,7 +145,6 @@ SUBDIR= \
if_disc \
if_edsc \
if_epair \
if_faith \
${_if_gif} \
${_if_gre} \
${_if_me} \

View File

@ -1,8 +0,0 @@
# $FreeBSD$
.PATH: ${.CURDIR}/../../net
KMOD= if_faith
SRCS= if_faith.c opt_inet.h opt_inet6.h
.include <bsd.kmod.mk>

View File

@ -1,331 +0,0 @@
/* $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

View File

@ -246,7 +246,6 @@
/* 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

View File

@ -428,8 +428,7 @@ __END_DECLS
#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 */
@ -630,7 +629,7 @@ int getsourcefilter(int, uint32_t, struct sockaddr *, socklen_t,
#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 */

View File

@ -1645,11 +1645,6 @@ in_pcblookup_group(struct inpcbinfo *pcbinfo, struct inpcbgroup *pcbgroup,
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,
@ -1724,11 +1719,6 @@ in_pcblookup_group(struct inpcbinfo *pcbinfo, struct inpcbgroup *pcbgroup,
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,
@ -1869,11 +1859,6 @@ in_pcblookup_hash_locked(struct inpcbinfo *pcbinfo, struct in_addr faddr,
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,
@ -2468,10 +2453,6 @@ db_print_inpflags(int inp_flags)
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;

View File

@ -511,7 +511,7 @@ short inp_so_options(const struct inpcb *inp);
#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 */

View File

@ -410,19 +410,6 @@ icmp_input(struct mbuf **mp, int *offp, int proto)
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,

View File

@ -104,12 +104,6 @@ SYSCTL_INT(_net_inet_ip, IPCTL_SENDREDIRECTS, redirect, CTLFLAG_VNET | CTLFLAG_R
&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,
@ -752,18 +746,6 @@ ip_input(struct mbuf *m)
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.
*/

View File

@ -991,7 +991,6 @@ ip_ctloutput(struct socket *so, struct sockopt *sopt)
case IP_RECVDSTADDR:
case IP_RECVTTL:
case IP_RECVIF:
case IP_FAITH:
case IP_ONESBCAST:
case IP_DONTFRAG:
case IP_RECVTOS:
@ -1058,10 +1057,6 @@ ip_ctloutput(struct socket *so, struct sockopt *sopt)
OPTSET(INP_RECVIF);
break;
case IP_FAITH:
OPTSET(INP_FAITH);
break;
case IP_ONESBCAST:
OPTSET(INP_ONESBCAST);
break;
@ -1200,7 +1195,6 @@ ip_ctloutput(struct socket *so, struct sockopt *sopt)
case IP_RECVTTL:
case IP_RECVIF:
case IP_PORTRANGE:
case IP_FAITH:
case IP_ONESBCAST:
case IP_DONTFRAG:
case IP_BINDANY:
@ -1259,10 +1253,6 @@ ip_ctloutput(struct socket *so, struct sockopt *sopt)
optval = 0;
break;
case IP_FAITH:
optval = OPTBIT(INP_FAITH);
break;
case IP_ONESBCAST:
optval = OPTBIT(INP_ONESBCAST);
break;

View File

@ -482,22 +482,6 @@ icmp6_input(struct mbuf **mp, int *offp, int proto)
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)

View File

@ -137,8 +137,6 @@ static int in6_notify_ifa(struct ifnet *, struct in6_ifaddr *,
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 *,
@ -1948,34 +1946,20 @@ in6if_do_dad(struct ifnet *ifp)
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);
}
/*

View File

@ -424,8 +424,7 @@ struct route_in6 {
#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 */
@ -580,7 +579,7 @@ struct ip6_mtuinfo {
#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
@ -669,7 +668,6 @@ extern void addrsel_policy_init(void);
#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

View File

@ -870,12 +870,6 @@ in6_pcblookup_group(struct inpcbinfo *pcbinfo, struct inpcbgroup *pcbgroup,
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.
@ -935,10 +929,6 @@ in6_pcblookup_group(struct inpcbinfo *pcbinfo, struct inpcbgroup *pcbgroup,
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,
@ -1001,10 +991,6 @@ in6_pcblookup_group(struct inpcbinfo *pcbinfo, struct inpcbgroup *pcbgroup,
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,
@ -1069,18 +1055,12 @@ in6_pcblookup_hash_locked(struct inpcbinfo *pcbinfo, struct in6_addr *faddr,
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.
*/
@ -1137,10 +1117,6 @@ in6_pcblookup_hash_locked(struct inpcbinfo *pcbinfo, struct in6_addr *faddr,
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,

View File

@ -434,7 +434,6 @@ VNET_DEFINE(int, ip6_rr_prune) = 5; /* router renumbering prefix
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;
@ -543,8 +542,6 @@ SYSCTL_INT(_net_inet6_ip6, IPV6CTL_RFC6204W3, rfc6204w3,
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,

View File

@ -1408,7 +1408,6 @@ ip6_ctloutput(struct socket *so, struct sockopt *sopt)
/* FALLTHROUGH */
case IPV6_UNICAST_HOPS:
case IPV6_HOPLIMIT:
case IPV6_FAITH:
case IPV6_RECVPKTINFO:
case IPV6_RECVHOPLIMIT:
@ -1552,10 +1551,6 @@ do { \
OPTSET(IN6P_RTHDR);
break;
case IPV6_FAITH:
OPTSET(INP_FAITH);
break;
case IPV6_RECVPATHMTU:
/*
* We ignore this option for TCP
@ -1823,7 +1818,6 @@ do { \
case IPV6_RECVRTHDR:
case IPV6_RECVPATHMTU:
case IPV6_FAITH:
case IPV6_V6ONLY:
case IPV6_PORTRANGE:
case IPV6_RECVTCLASS:
@ -1868,10 +1862,6 @@ do { \
optval = OPTBIT(IN6P_MTU);
break;
case IPV6_FAITH:
optval = OPTBIT(INP_FAITH);
break;
case IPV6_V6ONLY:
optval = OPTBIT(IN6P_IPV6_V6ONLY);
break;

View File

@ -296,7 +296,6 @@ VNET_DECLARE(int, ip6_norbit_raif); /* Disable R-bit in NA on RA
* 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
@ -310,7 +309,6 @@ VNET_DECLARE(int, ip6_dad_count); /* DupAddrDetectionTransmits */
#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)

View File

@ -169,12 +169,6 @@ rip6_input(struct mbuf **mp, int *offp, int proto)
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;

View File

@ -149,10 +149,6 @@ sctp6_input_with_port(struct mbuf **i_pak, int *offp, uint16_t port)
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) {

View File

@ -208,12 +208,6 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
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 *);

View File

@ -231,7 +231,6 @@ device vlan # 802.1Q VLAN support
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.

View File

@ -154,7 +154,6 @@ device tun # Packet tunnel.
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.

View File

@ -157,7 +157,6 @@ device tun # Packet tunnel.
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.

View File

@ -77,7 +77,6 @@ device vlan # 802.1Q VLAN support
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

View File

@ -225,7 +225,6 @@ device vlan # 802.1Q VLAN support
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.

View File

@ -1954,7 +1954,6 @@ OLD_FILES+=usr/share/man/man3/iconvlist.3.gz
.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

View File

@ -71,7 +71,6 @@ device tun
device pty
device md
device gif
device faith
device firmware
device bpf
device uhci

View File

@ -69,7 +69,6 @@ device tun
device pty
device md
device gif
device faith
device firmware
device bpf
device uhci

View File

@ -1311,14 +1311,6 @@ net.inet.ip.intr_queue_drops
---
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

View File

@ -148,7 +148,6 @@ device tun # Packet tunnel.
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!

View File

@ -138,7 +138,6 @@ device tun # Packet tunnel.
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!

View File

@ -110,7 +110,6 @@ device tun # Packet tunnel.
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!

View File

@ -160,7 +160,6 @@ SUBDIR+= gpioctl
.endif
.if ${MK_INET6} != "no"
SUBDIR+= faithd
SUBDIR+= ip6addrctl
SUBDIR+= mld6query
SUBDIR+= ndp

View File

@ -82,7 +82,7 @@ f_dialog_menu_netdev()
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

View File

@ -1,25 +0,0 @@
# Copyright (c) 1996 WIDE Project. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modifications, are permitted provided that the above copyright notice
# and this paragraph are duplicated in all such forms and that any
# documentation, advertising materials, and other materials related to
# such distribution and use acknowledge that the software was developed
# by the WIDE Project, Japan. The name of the Project may not be used to
# endorse or promote products derived from this software without
# specific prior written permission. THIS SOFTWARE IS PROVIDED ``AS IS''
# AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
# LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE.
#
# $FreeBSD$
PROG= faithd
MAN= faithd.8
SRCS= faithd.c tcp.c ftp.c prefix.c
CFLAGS+= -DHAVE_POLL_H
WARNS?= 2
.include <bsd.prog.mk>

View File

@ -1,148 +0,0 @@
Configuring FAITH IPv6-to-IPv4 TCP relay
Kazu Yamamoto and Jun-ichiro itojun Hagino
$KAME: README,v 1.10 2003/01/06 21:40:33 sumikawa Exp $
$FreeBSD$
Introduction
============
FAITH is an IPv6-to-IPv4 TCP relay. It performs tcp relay just as some of
firewall-oriented gateway does, but between IPv6 and IPv4 with address
translation.
TCP connections has to be made from IPv6 node to IPv4 node. FAITH will
not relay connections for the opposite direction.
To perform relays, FAITH daemon needs to be executed on a router between
your local IPv6 site and outside IPv4 network. The daemon needs to be
invoked per each TCP services (TCP port number).
IPv4 node "dest" = 123.4.5.6
|
[[[[ outside IPv4 ocean ]]]]
|
node that runs FAITH-daemon (usually a router)
|
==+=====+===+==== IPv6, or IPv4/v6 network in your site ^
| | | connection
clients IPv6 node "src" |
You will have to allocate an IPv6 address prefix to map IPv4 addresses into.
The following description uses 3ffe:0501:ffff:0000:: as example.
Please use a prefix which belongs to your site.
FAITH will make it possible to make an IPv6 TCP connection From IPv6 node
"src", toward IPv4 node "dest", by specifying FAITH-mapped address
3ffe:0501:ffff:0000::123.4.5.6
(which is, 3ffe:0501:ffff:0000:0000:0000:7b04:0506).
The address mapping can be performed by hand:-), by special nameserver on
the network, or by special resolver on the source node.
Setup
=====
The following example assumes:
- You have assigned 3ffe:0501:ffff:0000:: as FAITH adderss prefix.
- You are willing to provide IPv6-to IPv4 TCP relay for telnet.
<<On the translating router on which faithd runs>>
(1) If you have IPv6 TCP server for the "telnet" service, i.e. telnetd via
inet6d, disable that daemon. Comment out the line from "inet6d.conf"
and send the HUP signal to "inet6d".
(2) Execute sysctl as root to enable FAITH support in the kernel.
# sysctl net.inet6.ip6.keepfaith=1
(3) Route packets toward FAITH prefix into "faith0" interface.
# ifconfig faith0 up
# route add -inet6 3ffe:0501:ffff:0000:: -prefixlen 64 ::1
# route change -inet6 3ffe:0501:ffff:0000:: -prefixlen 64 -ifp faith0
(4) Execute "faithd" by root as follows:
# faithd telnet /usr/libexec/telnetd telnetd
1st argument is a service name you are willing to provide TCP relay.
(it can be specified either by number "23" or by string "telnet")
2nd argument is a path name for local IPv6 TCP server. If there is a
connection toward the router itself, this program will be invoked.
3rd and the following arguments are arguments for the local IPv6 TCP
server. (3rd argument is typically the program name without its path.)
More examples:
# faithd ftpd /usr/libexec/ftpd ftpd -l
# faithd sshd
If inetd(8) on your platform have special support for faithd, it is possible
to setup faithd services via inetd(8). Consult manpage for details.
<<Routing>>
(4) Make sure that packets whose destinations match the prefix can
reach from the IPv6 host to the translating router.
<<On the IPv6 host>>
There are two ways to translate IPv4 address to IPv6 address:
(a) Faked by DNS
(b) Faked by /etc/hosts.
(5.a) Install "newbie" and set up FAITH mode. See kit/ports/newbie.
(5.b) Add an entry into /etc/hosts so that you can resolve hostname into
faked IPv6 addrss. For example, add the following line for www.netbsd.org:
3ffe:0501:ffff:0000::140.160.140.252 www.netbsd.org
<<On the translating router on which faithd runs.>>
(6) To see if "faithd" works, watch "/var/log/daemon". Note: please
setup "/etc/syslog.conf" so that LOG_DAEMON messages are to be stored
in "/var/log/daemon".
<e.g.>
daemon.* /var/log/daemon
Access control
==============
Since faithd implements TCP relaying service, it is critical to implement
proper access control to cope with malicious use. Bad guy may try to
use your relay router to circumvent access controls, or may try to
abuse your network (like sending SPAMs from IPv4 address that belong to you).
Install IPv6 packet filter directives that would reject traffic from
unwanted source. If you are using inetd-based setup, you may be able to
use access control mechanisms in inetd.
Advanced configuration
======================
If you would like to restrict IPv4 destination for translation, you may
want to do the following:
# route add -inet6 3ffe:0501:ffff:0000::123.0.0.0 -prefixlen 104 ::1
# route change -inet6 3ffe:0501:ffff:0000::123.0.0.0 -prefixlen 104 \
-ifp faith0
By this way, you can restrict IPv4 destination to 123.0.0.0/8.
You may also want to reject packets toward 3ffe:0501:ffff:0000::/64 which
is not in 3ffe:0501:ffff:0000::123.0.0.0/104. This will be left as excerside
for the reader.
By doing this, you will be able to provide your IPv4 web server to outside
IPv6 customers, without risks of unwanted open relays.
[[[[ IPv6 network outside ]]]] |
| | connection
node that runs FAITH-daemon (usually a router) v
|
========+======== IPv4/v6 network in your site
| (123.0.0.0/8)
IPv4 web server

View File

@ -1,404 +0,0 @@
.\" $KAME: faithd.8,v 1.37 2002/05/09 14:21:23 itojun Exp $
.\"
.\" Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. Neither the name of the project nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD$
.\"
.Dd August 2, 2011
.Dt FAITHD 8
.Os
.Sh NAME
.Nm faithd
.Nd FAITH IPv6/v4 translator daemon
.Sh SYNOPSIS
.Nm
.Op Fl dp
.Op Fl f Ar configfile
.Ar service
.Op Ar serverpath Op Ar serverargs
.Sh DESCRIPTION
The
.Nm
utility provides IPv6-to-IPv4 TCP relaying.
It can only be used on an IPv4/v6 dual stack router.
.Pp
When
.Nm
receives
.Tn TCPv6
traffic, it will relay the
.Tn TCPv6
traffic to
.Tn TCPv4 .
The destination for the relayed
.Tn TCPv4
connection will be determined by the last 4 octets of the original
.Tn IPv6
destination.
For example, if
.Li 3ffe:0501:4819:ffff::
is reserved for
.Nm ,
and the
.Tn TCPv6
destination address is
.Li 3ffe:0501:4819:ffff::0a01:0101 ,
the traffic will be relayed to IPv4 destination
.Li 10.1.1.1 .
.Pp
To use the
.Nm
translation service,
an IPv6 address prefix must be reserved for mapping IPv4 addresses into.
The kernel must be properly configured to route all the TCP connections
toward the reserved IPv6 address prefix into the
.Xr faith 4
pseudo interface, using the
.Xr route 8
command.
Also,
.Xr sysctl 8
should be used to configure
.Dv net.inet6.ip6.keepfaith
to
.Dv 1 .
.Pp
The router must be configured to capture all the TCP traffic
for the reserved
.Tn IPv6
address prefix, by using
.Xr route 8
and
.Xr sysctl 8
commands.
.Pp
The
.Nm
utility needs special name-to-address translation logic, so that
hostnames get resolved into the special
.Tn IPv6
address prefix.
For small-scale installations, use
.Xr hosts 5 ;
For large-scale installations, it is useful to have
a DNS server with special address translation support.
An implementation called
.Nm totd
is available at
.Pa http://www.vermicelli.pasta.cs.uit.no/software/totd.html .
Make sure you do not propagate translated DNS records over to normal
DNS, as it can cause severe problems.
.Ss Daemon mode
When
.Nm
is invoked as a standalone program,
.Nm
will daemonize itself.
The
.Nm
utility will listen to
.Tn TCPv6
port
.Ar service .
If
.Tn TCPv6
traffic to port
.Ar service
is found, it relays the connection.
.Pp
Since
.Nm
listens to TCP port
.Ar service ,
it is not possible to run local TCP daemons for port
.Ar service
on the router, using
.Xr inetd 8
or other standard mechanisms.
By specifying
.Ar serverpath
to
.Nm ,
you can run local daemons on the router.
The
.Nm
utility will invoke a local daemon at
.Ar serverpath
if the destination address is a local interface address,
and will perform translation to IPv4 TCP in other cases.
You can also specify
.Ar serverargs
for the arguments for the local daemon.
.Pp
The following options are available:
.Bl -tag -width indent
.It Fl d
Debugging information will be generated using
.Xr syslog 3 .
.It Fl f Ar configfile
Specify a configuration file for access control.
See below.
.It Fl p
Use privileged TCP port number as source port,
for IPv4 TCP connection toward final destination.
For relaying
.Xr ftp 1 ,
this flag is not necessary as special program code is supplied.
.El
.Pp
The
.Nm
utility will relay both normal and out-of-band TCP data.
It is capable of emulating TCP half close as well.
The
.Nm
utility includes special support for protocols used by
.Xr ftp 1 .
When translating the FTP protocol,
.Nm
translates network level addresses in
.Li PORT/LPRT/EPRT
and
.Li PASV/LPSV/EPSV
commands.
.Pp
Inactive sessions will be disconnected in 30 minutes,
to prevent stale sessions from chewing up resources.
This may be inappropriate for some services
(should this be configurable?).
.Ss inetd mode
When
.Nm
is invoked via
.Xr inetd 8 ,
.Nm
will handle connections passed from standard input.
If the connection endpoint is in the reserved IPv6 address prefix,
.Nm
will relay the connection.
Otherwise,
.Nm
will invoke a service-specific daemon like
.Xr telnetd 8 ,
by using the command argument passed from
.Xr inetd 8 .
.Pp
The
.Nm
utility determines operation mode by the local TCP port number,
and enables special protocol handling whenever necessary/possible.
For example, if
.Nm
is invoked via
.Xr inetd 8
on the FTP port, it will operate as an FTP relay.
.Pp
The operation mode requires special support for
.Nm
in
.Xr inetd 8 .
.Ss Access control
To prevent malicious access,
.Nm
implements simple address-based access control.
With
.Pa /etc/faithd.conf
(or
.Ar configfile
specified by
.Fl f ) ,
.Nm
will avoid relaying unwanted traffic.
The
.Pa faithd.conf
configuration file contains directives of the following format:
.Bl -bullet
.It
.Ar src Ns / Ns Ar slen Cm deny Ar dst Ns / Ns Ar dlen
.Pp
If the source address of a query matches
.Ar src Ns / Ns Ar slen ,
and the translated destination address matches
.Ar dst Ns / Ns Ar dlen ,
deny the connection.
.It
.Ar src Ns / Ns Ar slen Cm permit Ar dst Ns / Ns Ar dlen
.Pp
If the source address of a query matches
.Ar src Ns / Ns Ar slen ,
and the translated destination address matches
.Ar dst Ns / Ns Ar dlen ,
permit the connection.
.El
.Pp
The directives are evaluated in sequence,
and the first matching entry will be effective.
If there is no match
(if we reach the end of the ruleset)
the traffic will be denied.
.Pp
With inetd mode,
traffic may be filtered by using access control functionality in
.Xr inetd 8 .
.Sh EXIT STATUS
The
.Nm
utility exits with
.Dv EXIT_SUCCESS
.Pq 0
on success, and
.Dv EXIT_FAILURE
.Pq 1
on error.
.Sh EXAMPLES
Before invoking
.Nm ,
the
.Xr faith 4
interface has to be configured properly.
.Bd -literal -offset indent
# sysctl net.inet6.ip6.accept_rtadv=0
# sysctl net.inet6.ip6.forwarding=1
# sysctl net.inet6.ip6.keepfaith=1
# ifconfig faith0 up
# route add -inet6 3ffe:501:4819:ffff:: -prefixlen 96 ::1
# route change -inet6 3ffe:501:4819:ffff:: -prefixlen 96 -ifp faith0
.Ed
.Ss Daemon mode samples
To translate
.Li telnet
service, and provide no local telnet service, invoke
.Nm
as follows:
.Bd -literal -offset indent
# faithd telnet
.Ed
.Pp
If you would like to provide local telnet service via
.Xr telnetd 8
on
.Pa /usr/libexec/telnetd ,
use the following command line:
.Bd -literal -offset indent
# faithd telnet /usr/libexec/telnetd telnetd
.Ed
.Pp
If you would like to pass extra arguments to the local daemon:
.Bd -literal -offset indent
# faithd ftp /usr/libexec/ftpd ftpd -l
.Ed
.Pp
Here are some other examples.
You may need
.Fl p
if the service checks the source port range.
.Bd -literal -offset indent
# faithd ssh
# faithd telnet /usr/libexec/telnetd telnetd
.Ed
.Ss inetd mode samples
Add the following lines into
.Xr inetd.conf 5 .
Syntax may vary depending upon your operating system.
.Bd -literal -offset indent
telnet stream tcp6/faith nowait root faithd telnetd
ftp stream tcp6/faith nowait root faithd ftpd -l
ssh stream tcp6/faith nowait root faithd /usr/sbin/sshd -i
.Ed
.Pp
.Xr inetd 8
will open listening sockets with kernel TCP relay support enabled.
Whenever a connection comes in,
.Nm
will be invoked by
.Xr inetd 8 .
If the connection endpoint is in the reserved IPv6 address prefix.
The
.Nm
utility will relay the connection.
Otherwise,
.Nm
will invoke service-specific daemon like
.Xr telnetd 8 .
.Ss Access control samples
The following illustrates a simple
.Pa faithd.conf
setting.
.Bd -literal -offset indent
# permit anyone from 3ffe:501:ffff::/48 to use the translator,
# to connect to the following IPv4 destinations:
# - any location except 10.0.0.0/8 and 127.0.0.0/8.
# Permit no other connections.
#
3ffe:501:ffff::/48 deny 10.0.0.0/8
3ffe:501:ffff::/48 deny 127.0.0.0/8
3ffe:501:ffff::/48 permit 0.0.0.0/0
.Ed
.Sh SEE ALSO
.Xr faith 4 ,
.Xr route 8 ,
.Xr sysctl 8
.Rs
.%A Jun-ichiro itojun Hagino
.%A Kazu Yamamoto
.%T "An IPv6-to-IPv4 transport relay translator"
.%B RFC3142
.%U http://tools.ietf.org/html/rfc3142
.%D June 2001
.Re
.\"
.Sh HISTORY
The
.Nm
utility first appeared in the WIDE Hydrangea IPv6 protocol stack kit.
.\"
.Pp
IPv6 and IPsec support based on the KAME Project (http://www.kame.net/) stack
was initially integrated into
.Fx 4.0 .
.Sh SECURITY CONSIDERATIONS
It is very insecure to use IP-address based authentication, for connections relayed by
.Nm ,
and any other TCP relaying services.
.Pp
Administrators are advised to limit accesses to
.Nm
using
.Pa faithd.conf ,
or by using IPv6 packet filters, to protect the
.Nm
service from malicious parties, and to avoid theft of service/bandwidth.
IPv6 destination addresses can be limited by
carefully configuring routing entries that point to
.Xr faith 4 ,
using
.Xr route 8 .
The IPv6 source address needs to be filtered using packet filters.
The documents listed in
.Sx SEE ALSO
have more information on this topic.

View File

@ -1,908 +0,0 @@
/* $KAME: faithd.c,v 1.67 2003/10/16 05:26:21 itojun Exp $ */
/*
* Copyright (C) 1997 and 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* User level translator from IPv6 to IPv4.
*
* Usage: faithd [<port> <progpath> <arg1(progname)> <arg2> ...]
* e.g. faithd telnet /usr/libexec/telnetd telnetd
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/types.h>
#include <sys/sysctl.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <libutil.h>
#ifdef HAVE_POLL_H
#include <poll.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <syslog.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <fcntl.h>
#include <termios.h>
#include <net/if_types.h>
#ifdef IFT_FAITH
# define USE_ROUTE
# include <net/if.h>
# include <net/route.h>
# include <net/if_dl.h>
#endif
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <ifaddrs.h>
#include "faithd.h"
#include "prefix.h"
char *serverpath = NULL;
char *serverarg[MAXARGV + 1];
static char *faithdname = NULL;
char logname[BUFSIZ];
char procname[BUFSIZ];
struct myaddrs {
struct myaddrs *next;
struct sockaddr *addr;
};
struct myaddrs *myaddrs = NULL;
static const char *service;
#ifdef USE_ROUTE
static int sockfd = 0;
#endif
int dflag = 0;
static int pflag = 0;
static int inetd = 0;
static char *configfile = NULL;
int main(int, char **);
static int inetd_main(int, char **);
static int daemon_main(int, char **);
static void play_service(int);
static void play_child(int, struct sockaddr *);
static int faith_prefix(struct sockaddr *);
static int map6to4(struct sockaddr_in6 *, struct sockaddr_in *);
static void sig_child(int);
static void sig_terminate(int);
static void start_daemon(void);
static void exit_stderr(const char *, ...)
__attribute__((__format__(__printf__, 1, 2)));
static void grab_myaddrs(void);
static void free_myaddrs(void);
static void update_myaddrs(void);
static void usage(void);
int
main(int argc, char **argv)
{
/*
* Initializing stuff
*/
faithdname = strrchr(argv[0], '/');
if (faithdname)
faithdname++;
else
faithdname = argv[0];
if (strcmp(faithdname, "faithd") != 0) {
inetd = 1;
return inetd_main(argc, argv);
} else
return daemon_main(argc, argv);
}
static int
inetd_main(int argc, char **argv)
{
char path[MAXPATHLEN];
struct sockaddr_storage me;
struct sockaddr_storage from;
socklen_t melen, fromlen;
int i;
int error;
const int on = 1;
char sbuf[NI_MAXSERV], snum[NI_MAXSERV];
if (config_load(configfile) < 0 && configfile) {
exit_failure("could not load config file");
/*NOTREACHED*/
}
if (strrchr(argv[0], '/') == NULL)
snprintf(path, sizeof(path), "%s/%s", DEFAULT_DIR, argv[0]);
else
snprintf(path, sizeof(path), "%s", argv[0]);
#ifdef USE_ROUTE
grab_myaddrs();
sockfd = socket(PF_ROUTE, SOCK_RAW, PF_UNSPEC);
if (sockfd < 0) {
exit_failure("socket(PF_ROUTE): %s", strerror(errno));
/*NOTREACHED*/
}
#endif
melen = sizeof(me);
if (getsockname(STDIN_FILENO, (struct sockaddr *)&me, &melen) < 0) {
exit_failure("getsockname: %s", strerror(errno));
/*NOTREACHED*/
}
fromlen = sizeof(from);
if (getpeername(STDIN_FILENO, (struct sockaddr *)&from, &fromlen) < 0) {
exit_failure("getpeername: %s", strerror(errno));
/*NOTREACHED*/
}
if (getnameinfo((struct sockaddr *)&me, melen, NULL, 0,
sbuf, sizeof(sbuf), NI_NUMERICHOST) == 0)
service = sbuf;
else
service = DEFAULT_PORT_NAME;
if (getnameinfo((struct sockaddr *)&me, melen, NULL, 0,
snum, sizeof(snum), NI_NUMERICHOST) != 0)
snprintf(snum, sizeof(snum), "?");
snprintf(logname, sizeof(logname), "faithd %s", snum);
snprintf(procname, sizeof(procname), "accepting port %s", snum);
openlog(logname, LOG_PID | LOG_NOWAIT, LOG_DAEMON);
if (argc >= MAXARGV) {
exit_failure("too many arguments");
/*NOTREACHED*/
}
serverarg[0] = serverpath = path;
for (i = 1; i < argc; i++)
serverarg[i] = argv[i];
serverarg[i] = NULL;
error = setsockopt(STDIN_FILENO, SOL_SOCKET, SO_OOBINLINE, &on,
sizeof(on));
if (error < 0) {
exit_failure("setsockopt(SO_OOBINLINE): %s", strerror(errno));
/*NOTREACHED*/
}
play_child(STDIN_FILENO, (struct sockaddr *)&from);
exit_failure("should not reach here");
return 0; /*dummy!*/
}
static int
daemon_main(int argc, char **argv)
{
struct addrinfo hints, *res;
int s_wld, error, i, serverargc, on = 1;
int family = AF_INET6;
int c;
while ((c = getopt(argc, argv, "df:p")) != -1) {
switch (c) {
case 'd':
dflag++;
break;
case 'f':
configfile = optarg;
break;
case 'p':
pflag++;
break;
default:
usage();
/*NOTREACHED*/
}
}
argc -= optind;
argv += optind;
if (config_load(configfile) < 0 && configfile) {
exit_failure("could not load config file");
/*NOTREACHED*/
}
#ifdef USE_ROUTE
grab_myaddrs();
#endif
switch (argc) {
case 0:
usage();
/*NOTREACHED*/
default:
serverargc = argc - NUMARG;
if (serverargc >= MAXARGV)
exit_stderr("too many arguments");
serverpath = strdup(argv[NUMPRG]);
if (!serverpath)
exit_stderr("not enough core");
for (i = 0; i < serverargc; i++) {
serverarg[i] = strdup(argv[i + NUMARG]);
if (!serverarg[i])
exit_stderr("not enough core");
}
serverarg[i] = NULL;
/* fall throuth */
case 1: /* no local service */
service = argv[NUMPRT];
break;
}
start_daemon();
/*
* Opening wild card socket for this service.
*/
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_PASSIVE;
hints.ai_family = family;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP; /* SCTP? */
error = getaddrinfo(NULL, service, &hints, &res);
if (error)
exit_failure("getaddrinfo: %s", gai_strerror(error));
s_wld = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (s_wld == -1)
exit_failure("socket: %s", strerror(errno));
#ifdef IPV6_FAITH
if (res->ai_family == AF_INET6) {
error = setsockopt(s_wld, IPPROTO_IPV6, IPV6_FAITH, &on, sizeof(on));
if (error == -1)
exit_failure("setsockopt(IPV6_FAITH): %s",
strerror(errno));
}
#endif
error = setsockopt(s_wld, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
if (error == -1)
exit_failure("setsockopt(SO_REUSEADDR): %s", strerror(errno));
error = setsockopt(s_wld, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on));
if (error == -1)
exit_failure("setsockopt(SO_OOBINLINE): %s", strerror(errno));
#ifdef IPV6_V6ONLY
error = setsockopt(s_wld, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on));
if (error == -1)
exit_failure("setsockopt(IPV6_V6ONLY): %s", strerror(errno));
#endif
error = bind(s_wld, (struct sockaddr *)res->ai_addr, res->ai_addrlen);
if (error == -1)
exit_failure("bind: %s", strerror(errno));
error = listen(s_wld, 5);
if (error == -1)
exit_failure("listen: %s", strerror(errno));
#ifdef USE_ROUTE
sockfd = socket(PF_ROUTE, SOCK_RAW, PF_UNSPEC);
if (sockfd < 0) {
exit_failure("socket(PF_ROUTE): %s", strerror(errno));
/*NOTREACHED*/
}
#endif
/*
* Everything is OK.
*/
snprintf(logname, sizeof(logname), "faithd %s", service);
snprintf(procname, sizeof(procname), "accepting port %s", service);
openlog(logname, LOG_PID | LOG_NOWAIT, LOG_DAEMON);
syslog(LOG_INFO, "Starting faith daemon for %s port", service);
play_service(s_wld);
/* NOTREACHED */
exit(1); /*pacify gcc*/
}
static void
play_service(int s_wld)
{
struct sockaddr_storage srcaddr;
socklen_t len;
int s_src;
pid_t child_pid;
#ifdef HAVE_POLL_H
struct pollfd pfd[2];
#else
fd_set rfds;
int maxfd;
#endif
int error;
/*
* Wait, accept, fork, faith....
*/
again:
setproctitle("%s", procname);
#ifdef HAVE_POLL_H
pfd[0].fd = s_wld;
pfd[0].events = POLLIN;
pfd[1].fd = -1;
pfd[1].revents = 0;
#else
FD_ZERO(&rfds);
if (s_wld >= FD_SETSIZE)
exit_failure("descriptor too big");
FD_SET(s_wld, &rfds);
maxfd = s_wld;
#endif
#ifdef USE_ROUTE
if (sockfd) {
#ifdef HAVE_POLL_H
pfd[1].fd = sockfd;
pfd[1].events = POLLIN;
#else
if (sockfd >= FD_SETSIZE)
exit_failure("descriptor too big");
FD_SET(sockfd, &rfds);
maxfd = (maxfd < sockfd) ? sockfd : maxfd;
#endif
}
#endif
#ifdef HAVE_POLL_H
error = poll(pfd, sizeof(pfd)/sizeof(pfd[0]), INFTIM);
#else
error = select(maxfd + 1, &rfds, NULL, NULL, NULL);
#endif
if (error < 0) {
if (errno == EINTR)
goto again;
exit_failure("select: %s", strerror(errno));
/*NOTREACHED*/
}
#ifdef USE_ROUTE
#ifdef HAVE_POLL_H
if (pfd[1].revents & POLLIN)
#else
if (FD_ISSET(sockfd, &rfds))
#endif
{
update_myaddrs();
}
#endif
#ifdef HAVE_POLL_H
if (pfd[0].revents & POLLIN)
#else
if (FD_ISSET(s_wld, &rfds))
#endif
{
len = sizeof(srcaddr);
s_src = accept(s_wld, (struct sockaddr *)&srcaddr, &len);
if (s_src < 0) {
if (errno == ECONNABORTED)
goto again;
exit_failure("socket: %s", strerror(errno));
/*NOTREACHED*/
}
if (srcaddr.ss_family == AF_INET6 &&
IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&srcaddr)->sin6_addr)) {
close(s_src);
syslog(LOG_ERR, "connection from IPv4 mapped address?");
goto again;
}
child_pid = fork();
if (child_pid == 0) {
/* child process */
close(s_wld);
closelog();
openlog(logname, LOG_PID | LOG_NOWAIT, LOG_DAEMON);
play_child(s_src, (struct sockaddr *)&srcaddr);
exit_failure("should never reach here");
/*NOTREACHED*/
} else {
/* parent process */
close(s_src);
if (child_pid == -1)
syslog(LOG_ERR, "can't fork");
}
}
goto again;
}
static void
play_child(int s_src, struct sockaddr *srcaddr)
{
struct sockaddr_storage dstaddr6;
struct sockaddr_storage dstaddr4;
char src[NI_MAXHOST];
char dst6[NI_MAXHOST];
char dst4[NI_MAXHOST];
socklen_t len = sizeof(dstaddr6);
int s_dst, error, hport, nresvport, on = 1;
struct timeval tv;
struct sockaddr *sa4;
const struct config *conf;
tv.tv_sec = 1;
tv.tv_usec = 0;
getnameinfo(srcaddr, srcaddr->sa_len,
src, sizeof(src), NULL, 0, NI_NUMERICHOST);
syslog(LOG_INFO, "accepted a client from %s", src);
error = getsockname(s_src, (struct sockaddr *)&dstaddr6, &len);
if (error == -1) {
exit_failure("getsockname: %s", strerror(errno));
/*NOTREACHED*/
}
getnameinfo((struct sockaddr *)&dstaddr6, len,
dst6, sizeof(dst6), NULL, 0, NI_NUMERICHOST);
syslog(LOG_INFO, "the client is connecting to %s", dst6);
if (!faith_prefix((struct sockaddr *)&dstaddr6)) {
if (serverpath) {
/*
* Local service
*/
syslog(LOG_INFO, "executing local %s", serverpath);
if (!inetd) {
dup2(s_src, 0);
close(s_src);
dup2(0, 1);
dup2(0, 2);
}
execv(serverpath, serverarg);
syslog(LOG_ERR, "execv %s: %s", serverpath,
strerror(errno));
_exit(EXIT_FAILURE);
} else {
close(s_src);
exit_success("no local service for %s", service);
}
}
/*
* Act as a translator
*/
switch (((struct sockaddr *)&dstaddr6)->sa_family) {
case AF_INET6:
if (!map6to4((struct sockaddr_in6 *)&dstaddr6,
(struct sockaddr_in *)&dstaddr4)) {
close(s_src);
exit_failure("map6to4 failed");
/*NOTREACHED*/
}
syslog(LOG_INFO, "translating from v6 to v4");
break;
default:
close(s_src);
exit_failure("family not supported");
/*NOTREACHED*/
}
sa4 = (struct sockaddr *)&dstaddr4;
getnameinfo(sa4, sa4->sa_len,
dst4, sizeof(dst4), NULL, 0, NI_NUMERICHOST);
conf = config_match(srcaddr, sa4);
if (!conf || !conf->permit) {
close(s_src);
if (conf) {
exit_failure("translation to %s not permitted for %s",
dst4, prefix_string(&conf->match));
/*NOTREACHED*/
} else {
exit_failure("translation to %s not permitted", dst4);
/*NOTREACHED*/
}
}
syslog(LOG_INFO, "the translator is connecting to %s", dst4);
setproctitle("port %s, %s -> %s", service, src, dst4);
if (sa4->sa_family == AF_INET6)
hport = ntohs(((struct sockaddr_in6 *)&dstaddr4)->sin6_port);
else /* AF_INET */
hport = ntohs(((struct sockaddr_in *)&dstaddr4)->sin_port);
if (pflag)
s_dst = rresvport_af(&nresvport, sa4->sa_family);
else
s_dst = socket(sa4->sa_family, SOCK_STREAM, 0);
if (s_dst < 0) {
exit_failure("socket: %s", strerror(errno));
/*NOTREACHED*/
}
if (conf->src.a.ss_family) {
if (bind(s_dst, (const struct sockaddr *)&conf->src.a,
conf->src.a.ss_len) < 0) {
exit_failure("bind: %s", strerror(errno));
/*NOTREACHED*/
}
}
error = setsockopt(s_dst, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on));
if (error < 0) {
exit_failure("setsockopt(SO_OOBINLINE): %s", strerror(errno));
/*NOTREACHED*/
}
error = setsockopt(s_src, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
if (error < 0) {
exit_failure("setsockopt(SO_SNDTIMEO): %s", strerror(errno));
/*NOTREACHED*/
}
error = setsockopt(s_dst, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
if (error < 0) {
exit_failure("setsockopt(SO_SNDTIMEO): %s", strerror(errno));
/*NOTREACHED*/
}
error = connect(s_dst, sa4, sa4->sa_len);
if (error < 0) {
exit_failure("connect: %s", strerror(errno));
/*NOTREACHED*/
}
switch (hport) {
case FTP_PORT:
ftp_relay(s_src, s_dst);
break;
default:
tcp_relay(s_src, s_dst, service);
break;
}
/* NOTREACHED */
}
/* 0: non faith, 1: faith */
static int
faith_prefix(struct sockaddr *dst)
{
#ifndef USE_ROUTE
int mib[4], size;
struct in6_addr faith_prefix;
struct sockaddr_in6 *dst6 = (struct sockaddr_in *)dst;
if (dst->sa_family != AF_INET6)
return 0;
mib[0] = CTL_NET;
mib[1] = PF_INET6;
mib[2] = IPPROTO_IPV6;
mib[3] = IPV6CTL_FAITH_PREFIX;
size = sizeof(struct in6_addr);
if (sysctl(mib, 4, &faith_prefix, &size, NULL, 0) < 0) {
exit_failure("sysctl: %s", strerror(errno));
/*NOTREACHED*/
}
if (memcmp(dst, &faith_prefix,
sizeof(struct in6_addr) - sizeof(struct in_addr) == 0) {
return 1;
}
return 0;
#else
struct myaddrs *p;
struct sockaddr_in6 *sin6;
struct sockaddr_in *sin4;
struct sockaddr_in6 *dst6;
struct sockaddr_in *dst4;
struct sockaddr_in dstmap;
dst6 = (struct sockaddr_in6 *)dst;
if (dst->sa_family == AF_INET6
&& IN6_IS_ADDR_V4MAPPED(&dst6->sin6_addr)) {
/* ugly... */
memset(&dstmap, 0, sizeof(dstmap));
dstmap.sin_family = AF_INET;
dstmap.sin_len = sizeof(dstmap);
memcpy(&dstmap.sin_addr, &dst6->sin6_addr.s6_addr[12],
sizeof(dstmap.sin_addr));
dst = (struct sockaddr *)&dstmap;
}
dst6 = (struct sockaddr_in6 *)dst;
dst4 = (struct sockaddr_in *)dst;
for (p = myaddrs; p; p = p->next) {
sin6 = (struct sockaddr_in6 *)p->addr;
sin4 = (struct sockaddr_in *)p->addr;
if (p->addr->sa_len != dst->sa_len
|| p->addr->sa_family != dst->sa_family)
continue;
switch (dst->sa_family) {
case AF_INET6:
if (sin6->sin6_scope_id == dst6->sin6_scope_id
&& IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &dst6->sin6_addr))
return 0;
break;
case AF_INET:
if (sin4->sin_addr.s_addr == dst4->sin_addr.s_addr)
return 0;
break;
}
}
return 1;
#endif
}
/* 0: non faith, 1: faith */
static int
map6to4(struct sockaddr_in6 *dst6, struct sockaddr_in *dst4)
{
memset(dst4, 0, sizeof(*dst4));
dst4->sin_len = sizeof(*dst4);
dst4->sin_family = AF_INET;
dst4->sin_port = dst6->sin6_port;
memcpy(&dst4->sin_addr, &dst6->sin6_addr.s6_addr[12],
sizeof(dst4->sin_addr));
if (dst4->sin_addr.s_addr == INADDR_ANY
|| dst4->sin_addr.s_addr == INADDR_BROADCAST
|| IN_MULTICAST(ntohl(dst4->sin_addr.s_addr)))
return 0;
return 1;
}
static void
sig_child(int sig __unused)
{
int status;
pid_t pid;
while ((pid = wait3(&status, WNOHANG, (struct rusage *)0)) > 0)
if (WEXITSTATUS(status))
syslog(LOG_WARNING, "child %ld exit status 0x%x",
(long)pid, status);
}
void
sig_terminate(int sig __unused)
{
syslog(LOG_INFO, "Terminating faith daemon");
exit(EXIT_SUCCESS);
}
static void
start_daemon(void)
{
#ifdef SA_NOCLDWAIT
struct sigaction sa;
#endif
if (daemon(0, 0) == -1)
exit_stderr("daemon: %s", strerror(errno));
#ifdef SA_NOCLDWAIT
memset(&sa, 0, sizeof(sa));
sa.sa_handler = sig_child;
sa.sa_flags = SA_NOCLDWAIT;
sigemptyset(&sa.sa_mask);
sigaction(SIGCHLD, &sa, (struct sigaction *)0);
#else
if (signal(SIGCHLD, sig_child) == SIG_ERR) {
exit_failure("signal CHLD: %s", strerror(errno));
/*NOTREACHED*/
}
#endif
if (signal(SIGTERM, sig_terminate) == SIG_ERR) {
exit_failure("signal TERM: %s", strerror(errno));
/*NOTREACHED*/
}
}
static void
exit_stderr(const char *fmt, ...)
{
va_list ap;
char buf[BUFSIZ];
va_start(ap, fmt);
vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
fprintf(stderr, "%s\n", buf);
exit(EXIT_FAILURE);
}
void
exit_failure(const char *fmt, ...)
{
va_list ap;
char buf[BUFSIZ];
va_start(ap, fmt);
vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
syslog(LOG_ERR, "%s", buf);
exit(EXIT_FAILURE);
}
void
exit_success(const char *fmt, ...)
{
va_list ap;
char buf[BUFSIZ];
va_start(ap, fmt);
vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
syslog(LOG_INFO, "%s", buf);
exit(EXIT_SUCCESS);
}
#ifdef USE_ROUTE
static void
grab_myaddrs(void)
{
struct ifaddrs *ifap, *ifa;
struct myaddrs *p;
struct sockaddr_in6 *sin6;
if (getifaddrs(&ifap) != 0) {
exit_failure("getifaddrs");
/*NOTREACHED*/
}
for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
switch (ifa->ifa_addr->sa_family) {
case AF_INET:
case AF_INET6:
break;
default:
continue;
}
p = (struct myaddrs *)malloc(sizeof(struct myaddrs) +
ifa->ifa_addr->sa_len);
if (!p) {
exit_failure("not enough core");
/*NOTREACHED*/
}
memcpy(p + 1, ifa->ifa_addr, ifa->ifa_addr->sa_len);
p->next = myaddrs;
p->addr = (struct sockaddr *)(p + 1);
#ifdef __KAME__
if (ifa->ifa_addr->sa_family == AF_INET6) {
sin6 = (struct sockaddr_in6 *)p->addr;
if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)
|| IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) {
sin6->sin6_scope_id =
ntohs(*(u_int16_t *)&sin6->sin6_addr.s6_addr[2]);
sin6->sin6_addr.s6_addr[2] = 0;
sin6->sin6_addr.s6_addr[3] = 0;
}
}
#endif
myaddrs = p;
if (dflag) {
char hbuf[NI_MAXHOST];
getnameinfo(p->addr, p->addr->sa_len,
hbuf, sizeof(hbuf), NULL, 0,
NI_NUMERICHOST);
syslog(LOG_INFO, "my interface: %s %s", hbuf,
ifa->ifa_name);
}
}
freeifaddrs(ifap);
}
static void
free_myaddrs(void)
{
struct myaddrs *p, *q;
p = myaddrs;
while (p) {
q = p->next;
free(p);
p = q;
}
myaddrs = NULL;
}
static void
update_myaddrs(void)
{
char msg[BUFSIZ];
int len;
struct rt_msghdr *rtm;
len = read(sockfd, msg, sizeof(msg));
if (len < 0) {
syslog(LOG_ERR, "read(PF_ROUTE) failed");
return;
}
rtm = (struct rt_msghdr *)msg;
if (len < 4 || len < rtm->rtm_msglen) {
syslog(LOG_ERR, "read(PF_ROUTE) short read");
return;
}
if (rtm->rtm_version != RTM_VERSION) {
syslog(LOG_ERR, "routing socket version mismatch");
close(sockfd);
sockfd = 0;
return;
}
switch (rtm->rtm_type) {
case RTM_NEWADDR:
case RTM_DELADDR:
case RTM_IFINFO:
break;
default:
return;
}
/* XXX more filters here? */
syslog(LOG_INFO, "update interface address list");
free_myaddrs();
grab_myaddrs();
}
#endif /*USE_ROUTE*/
static void
usage(void)
{
fprintf(stderr, "usage: %s [-dp] [-f conf] service [serverpath [serverargs]]\n",
faithdname);
exit(0);
}

View File

@ -1,70 +0,0 @@
/* $KAME: faithd.h,v 1.9 2002/05/09 09:41:24 itojun Exp $ */
/*
* Copyright (C) 1997 and 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
extern char logname[];
extern int dflag;
extern void tcp_relay(int, int, const char *);
extern void ftp_relay(int, int);
extern int ftp_active(int, int, int *, int *);
extern int ftp_passive(int, int, int *, int *);
extern void exit_success(const char *, ...)
__attribute__((__format__(__printf__, 1, 2)));
extern void exit_failure(const char *, ...)
__attribute__((__format__(__printf__, 1, 2)));
#define DEFAULT_PORT_NAME "telnet"
#define DEFAULT_DIR "/usr/libexec"
#define DEFAULT_NAME "telnetd"
#define DEFAULT_PATH (DEFAULT_DIR "/" DEFAULT_NAME)
#define FTP_PORT 21
#define RLOGIN_PORT 513
#define RSH_PORT 514
#define RETURN_SUCCESS 0
#define RETURN_FAILURE 1
#define YES 1
#define NO 0
#define MSS 2048
#define MAXARGV 20
#define NUMPRT 0
#define NUMPRG 1
#define NUMARG 2
#define UC(b) (((int)b)&0xff)
#define FAITH_TIMEOUT (30 * 60) /*second*/

File diff suppressed because it is too large Load Diff

View File

@ -1,345 +0,0 @@
/* $KAME: prefix.c,v 1.13 2003/09/02 22:50:17 itojun Exp $ */
/* $FreeBSD$ */
/*
* Copyright (C) 2000 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <netdb.h>
#include <string.h>
#include <stddef.h>
#include <stdlib.h>
#include <limits.h>
#ifndef offsetof
#define offsetof(type, member) ((size_t)(u_long)(&((type *)0)->member))
#endif
#include "faithd.h"
#include "prefix.h"
static int prefix_set(const char *, struct prefix *, int);
static struct config *config_load1(const char *);
#if 0
static void config_show1(const struct config *);
static void config_show(void);
#endif
struct config *config_list = NULL;
const int niflags = NI_NUMERICHOST;
static int
prefix_set(const char *s, struct prefix *prefix, int slash)
{
char *p = NULL, *q, *r;
struct addrinfo hints, *res = NULL;
int max;
p = strdup(s);
if (!p)
goto fail;
q = strchr(p, '/');
if (q) {
if (!slash)
goto fail;
*q++ = '\0';
}
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM; /*dummy*/
hints.ai_flags = AI_NUMERICHOST;
if (getaddrinfo(p, "0", &hints, &res))
goto fail;
if (res->ai_next || res->ai_addrlen > sizeof(prefix->a))
goto fail;
memcpy(&prefix->a, res->ai_addr, res->ai_addrlen);
switch (prefix->a.ss_family) {
case AF_INET:
max = 32;
break;
case AF_INET6:
max = 128;
break;
default:
max = -1;
break;
}
if (q) {
r = NULL;
prefix->l = (int)strtoul(q, &r, 10);
if (!*q || *r)
goto fail;
if (prefix->l < 0 || prefix->l > max)
goto fail;
} else
prefix->l = max;
if (p)
free(p);
if (res)
freeaddrinfo(res);
return 0;
fail:
if (p)
free(p);
if (res)
freeaddrinfo(res);
return -1;
}
const char *
prefix_string(const struct prefix *prefix)
{
static char buf[NI_MAXHOST + 20];
char hbuf[NI_MAXHOST];
if (getnameinfo((const struct sockaddr *)&prefix->a, prefix->a.ss_len,
hbuf, sizeof(hbuf), NULL, 0, niflags))
return NULL;
snprintf(buf, sizeof(buf), "%s/%d", hbuf, prefix->l);
return buf;
}
int
prefix_match(const struct prefix *prefix, const struct sockaddr *sa)
{
struct sockaddr_storage a, b;
char *pa, *pb;
int off, l;
if (prefix->a.ss_family != sa->sa_family ||
prefix->a.ss_len != sa->sa_len)
return 0;
if (prefix->a.ss_len > sizeof(a) || sa->sa_len > sizeof(b))
return 0;
switch (prefix->a.ss_family) {
case AF_INET:
off = offsetof(struct sockaddr_in, sin_addr);
break;
case AF_INET6:
off = offsetof(struct sockaddr_in6, sin6_addr);
break;
default:
if (memcmp(&prefix->a, sa, prefix->a.ss_len) != 0)
return 0;
else
return 1;
}
memcpy(&a, &prefix->a, prefix->a.ss_len);
memcpy(&b, sa, sa->sa_len);
l = prefix->l / 8 + (prefix->l % 8 ? 1 : 0);
/* overrun check */
if (off + l > a.ss_len)
return 0;
pa = ((char *)&a) + off;
pb = ((char *)&b) + off;
if (prefix->l % 8) {
pa[prefix->l / 8] &= 0xff00 >> (prefix->l % 8);
pb[prefix->l / 8] &= 0xff00 >> (prefix->l % 8);
}
if (memcmp(pa, pb, l) != 0)
return 0;
else
return 1;
}
/*
* prefix/prefixlen permit/deny prefix/prefixlen [srcaddr]
* 3ffe::/16 permit 10.0.0.0/8 10.1.1.1
*/
static struct config *
config_load1(const char *line)
{
struct config *conf;
char buf[BUFSIZ];
char *p;
char *token[4];
int i;
if (strlen(line) + 1 > sizeof(buf))
return NULL;
strlcpy(buf, line, sizeof(buf));
p = strchr(buf, '\n');
if (!p)
return NULL;
*p = '\0';
p = strchr(buf, '#');
if (p)
*p = '\0';
if (strlen(buf) == 0)
return NULL;
p = buf;
memset(token, 0, sizeof(token));
for (i = 0; i < sizeof(token) / sizeof(token[0]); i++) {
token[i] = strtok(p, "\t ");
p = NULL;
if (token[i] == NULL)
break;
}
/* extra tokens? */
if (strtok(p, "\t ") != NULL)
return NULL;
/* insufficient tokens */
switch (i) {
case 3:
case 4:
break;
default:
return NULL;
}
conf = (struct config *)malloc(sizeof(*conf));
if (conf == NULL)
return NULL;
memset(conf, 0, sizeof(*conf));
if (strcasecmp(token[1], "permit") == 0)
conf->permit = 1;
else if (strcasecmp(token[1], "deny") == 0)
conf->permit = 0;
else {
/* invalid keyword is considered as "deny" */
conf->permit = 0;
}
if (prefix_set(token[0], &conf->match, 1) < 0)
goto fail;
if (prefix_set(token[2], &conf->dest, 1) < 0)
goto fail;
if (token[3]) {
if (prefix_set(token[3], &conf->src, 0) < 0)
goto fail;
}
return conf;
fail:
free(conf);
return NULL;
}
int
config_load(const char *configfile)
{
FILE *fp;
char buf[BUFSIZ];
struct config *conf, *p;
struct config sentinel;
config_list = NULL;
if (!configfile)
configfile = _PATH_PREFIX_CONF;
fp = fopen(configfile, "r");
if (fp == NULL)
return -1;
p = &sentinel;
sentinel.next = NULL;
while (fgets(buf, sizeof(buf), fp) != NULL) {
conf = config_load1(buf);
if (conf) {
p->next = conf;
p = p->next;
}
}
config_list = sentinel.next;
fclose(fp);
return 0;
}
#if 0
static void
config_show1(const struct config *conf)
{
const char *p;
p = prefix_string(&conf->match);
printf("%s", p ? p : "?");
if (conf->permit)
printf(" permit");
else
printf(" deny");
p = prefix_string(&conf->dest);
printf(" %s", p ? p : "?");
printf("\n");
}
static void
config_show()
{
struct config *conf;
for (conf = config_list; conf; conf = conf->next)
config_show1(conf);
}
#endif
const struct config *
config_match(struct sockaddr *sa1, struct sockaddr *sa2)
{
static struct config conf;
const struct config *p;
if (sa1->sa_len > sizeof(conf.match.a) ||
sa2->sa_len > sizeof(conf.dest.a))
return NULL;
memset(&conf, 0, sizeof(conf));
if (!config_list) {
conf.permit = 1;
memcpy(&conf.match.a, sa1, sa1->sa_len);
memcpy(&conf.dest.a, sa2, sa2->sa_len);
return &conf;
}
for (p = config_list; p; p = p->next)
if (prefix_match(&p->match, sa1) && prefix_match(&p->dest, sa2))
return p;
return NULL;
}

View File

@ -1,52 +0,0 @@
/* $KAME: prefix.h,v 1.4 2001/09/05 03:04:21 itojun Exp $ */
/* $FreeBSD$ */
/*
* Copyright (C) 2000 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
struct prefix {
struct sockaddr_storage a;
int l;
};
struct config {
struct config *next;
int permit;
struct prefix match;
struct prefix dest;
struct prefix src; /* src to use for outgoing connection */
};
#define _PATH_PREFIX_CONF "/etc/faithd.conf"
extern const char *prefix_string(const struct prefix *);
extern int prefix_match(const struct prefix *, const struct sockaddr *);
extern int config_load(const char *);
extern const struct config *config_match(struct sockaddr *, struct sockaddr *);

View File

@ -1,324 +0,0 @@
/* $KAME: tcp.c,v 1.13 2003/09/02 22:49:21 itojun Exp $ */
/*
* Copyright (C) 1997 and 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include "faithd.h"
static char tcpbuf[16*1024];
/* bigger than MSS and may be lesser than window size */
static int tblen, tboff, oob_exists;
static fd_set readfds, writefds, exceptfds;
static char atmark_buf[2];
static pid_t cpid = (pid_t)0;
static pid_t ppid = (pid_t)0;
volatile time_t child_lastactive = (time_t)0;
static time_t parent_lastactive = (time_t)0;
static void sig_ctimeout(int);
static void sig_child(int);
static void notify_inactive(void);
static void notify_active(void);
static void send_data(int, int, const char *, int);
static void relay(int, int, const char *, int);
/*
* Inactivity timer:
* - child side (ppid != 0) will send SIGUSR1 to parent every (FAITH_TIMEOUT/4)
* second if traffic is active. if traffic is inactive, don't send SIGUSR1.
* - parent side (ppid == 0) will check the last SIGUSR1 it have seen.
*/
static void
sig_ctimeout(int sig __unused)
{
/* parent side: record notification from the child */
if (dflag)
syslog(LOG_DEBUG, "activity timer from child");
child_lastactive = time(NULL);
}
/* parent will terminate if child dies. */
static void
sig_child(int sig __unused)
{
int status;
pid_t pid;
pid = wait3(&status, WNOHANG, (struct rusage *)0);
if (pid > 0 && WEXITSTATUS(status))
syslog(LOG_WARNING, "child %ld exit status 0x%x",
(long)pid, status);
exit_success("terminate connection due to child termination");
}
static void
notify_inactive()
{
time_t t;
/* only on parent side... */
if (ppid)
return;
/* parent side should check for timeout. */
t = time(NULL);
if (dflag) {
syslog(LOG_DEBUG, "parent side %sactive, child side %sactive",
(FAITH_TIMEOUT < t - parent_lastactive) ? "in" : "",
(FAITH_TIMEOUT < t - child_lastactive) ? "in" : "");
}
if (FAITH_TIMEOUT < t - child_lastactive
&& FAITH_TIMEOUT < t - parent_lastactive) {
/* both side timeouted */
signal(SIGCHLD, SIG_DFL);
kill(cpid, SIGTERM);
wait(NULL);
exit_failure("connection timeout");
/* NOTREACHED */
}
}
static void
notify_active()
{
if (ppid) {
/* child side: notify parent of active traffic */
time_t t;
t = time(NULL);
if (FAITH_TIMEOUT / 4 < t - child_lastactive) {
if (kill(ppid, SIGUSR1) < 0) {
exit_failure("terminate connection due to parent termination");
/* NOTREACHED */
}
child_lastactive = t;
}
} else {
/* parent side */
parent_lastactive = time(NULL);
}
}
static void
send_data(int s_rcv, int s_snd, const char *service __unused, int direction)
{
int cc;
if (oob_exists) {
cc = send(s_snd, atmark_buf, 1, MSG_OOB);
if (cc == -1)
goto retry_or_err;
oob_exists = 0;
if (s_rcv >= FD_SETSIZE)
exit_failure("descriptor too big");
FD_SET(s_rcv, &exceptfds);
}
for (; tboff < tblen; tboff += cc) {
cc = write(s_snd, tcpbuf + tboff, tblen - tboff);
if (cc < 0)
goto retry_or_err;
}
#ifdef DEBUG
if (tblen) {
if (tblen >= sizeof(tcpbuf))
tblen = sizeof(tcpbuf) - 1;
tcpbuf[tblen] = '\0';
syslog(LOG_DEBUG, "from %s (%dbytes): %s",
direction == 1 ? "client" : "server", tblen, tcpbuf);
}
#endif /* DEBUG */
tblen = 0; tboff = 0;
if (s_snd >= FD_SETSIZE)
exit_failure("descriptor too big");
FD_CLR(s_snd, &writefds);
if (s_rcv >= FD_SETSIZE)
exit_failure("descriptor too big");
FD_SET(s_rcv, &readfds);
return;
retry_or_err:
if (errno != EAGAIN)
exit_failure("writing relay data failed: %s", strerror(errno));
if (s_snd >= FD_SETSIZE)
exit_failure("descriptor too big");
FD_SET(s_snd, &writefds);
}
static void
relay(int s_rcv, int s_snd, const char *service, int direction)
{
int atmark, error, maxfd;
struct timeval tv;
fd_set oreadfds, owritefds, oexceptfds;
FD_ZERO(&readfds);
FD_ZERO(&writefds);
FD_ZERO(&exceptfds);
fcntl(s_snd, F_SETFD, O_NONBLOCK);
oreadfds = readfds; owritefds = writefds; oexceptfds = exceptfds;
if (s_rcv >= FD_SETSIZE)
exit_failure("descriptor too big");
FD_SET(s_rcv, &readfds);
FD_SET(s_rcv, &exceptfds);
oob_exists = 0;
maxfd = (s_rcv > s_snd) ? s_rcv : s_snd;
for (;;) {
tv.tv_sec = FAITH_TIMEOUT / 4;
tv.tv_usec = 0;
oreadfds = readfds;
owritefds = writefds;
oexceptfds = exceptfds;
error = select(maxfd + 1, &readfds, &writefds, &exceptfds, &tv);
if (error == -1) {
if (errno == EINTR)
continue;
exit_failure("select: %s", strerror(errno));
} else if (error == 0) {
readfds = oreadfds;
writefds = owritefds;
exceptfds = oexceptfds;
notify_inactive();
continue;
}
/* activity notification */
notify_active();
if (FD_ISSET(s_rcv, &exceptfds)) {
error = ioctl(s_rcv, SIOCATMARK, &atmark);
if (error != -1 && atmark == 1) {
int cc;
oob_read_retry:
cc = read(s_rcv, atmark_buf, 1);
if (cc == 1) {
if (s_rcv >= FD_SETSIZE)
exit_failure("descriptor too big");
FD_CLR(s_rcv, &exceptfds);
if (s_snd >= FD_SETSIZE)
exit_failure("descriptor too big");
FD_SET(s_snd, &writefds);
oob_exists = 1;
} else if (cc == -1) {
if (errno == EINTR)
goto oob_read_retry;
exit_failure("reading oob data failed"
": %s",
strerror(errno));
}
}
}
if (FD_ISSET(s_rcv, &readfds)) {
relaydata_read_retry:
tblen = read(s_rcv, tcpbuf, sizeof(tcpbuf));
tboff = 0;
switch (tblen) {
case -1:
if (errno == EINTR)
goto relaydata_read_retry;
exit_failure("reading relay data failed: %s",
strerror(errno));
/* NOTREACHED */
case 0:
/* to close opposite-direction relay process */
shutdown(s_snd, 0);
close(s_rcv);
close(s_snd);
exit_success("terminating %s relay", service);
/* NOTREACHED */
default:
if (s_rcv >= FD_SETSIZE)
exit_failure("descriptor too big");
FD_CLR(s_rcv, &readfds);
if (s_snd >= FD_SETSIZE)
exit_failure("descriptor too big");
FD_SET(s_snd, &writefds);
break;
}
}
if (FD_ISSET(s_snd, &writefds))
send_data(s_rcv, s_snd, service, direction);
}
}
void
tcp_relay(int s_src, int s_dst, const char *service)
{
syslog(LOG_INFO, "starting %s relay", service);
child_lastactive = parent_lastactive = time(NULL);
cpid = fork();
switch (cpid) {
case -1:
exit_failure("tcp_relay: can't fork grand child: %s",
strerror(errno));
/* NOTREACHED */
case 0:
/* child process: relay going traffic */
ppid = getppid();
/* this is child so reopen log */
closelog();
openlog(logname, LOG_PID | LOG_NOWAIT, LOG_DAEMON);
relay(s_src, s_dst, service, 1);
/* NOTREACHED */
default:
/* parent process: relay coming traffic */
ppid = (pid_t)0;
signal(SIGUSR1, sig_ctimeout);
signal(SIGCHLD, sig_child);
relay(s_dst, s_src, service, 0);
/* NOTREACHED */
}
}

View File

@ -1,312 +0,0 @@
# faithd, ruby version. requires v6-enabled ruby.
#
# highly experimental (not working right at all) and very limited
# functionality.
#
# $Id: faithd.rb,v 1.1.2.4 1999/05/10 17:06:30 itojun Exp $
# $FreeBSD$
require "socket"
require "thread"
# XXX should be derived from system headers
IPPROTO_IPV6 = 41
IPV6_FAITH = 29
DEBUG = true
DEBUG_LOOPBACK = true
# TODO: OOB data handling
def tcpcopy(s1, s2, m)
STDERR.print "tcpcopy #{s1} #{s2}\n" if DEBUG
buf = ""
while TRUE
begin
buf = s1.sysread(100)
s2.syswrite(buf)
rescue EOFError
break
rescue IOError
break
end
end
STDERR.print "tcpcopy #{s1} #{s2} finished\n" if DEBUG
s1.shutdown(0)
s2.shutdown(1)
end
def relay_ftp_passiveconn(s6, s4, dport6, dport4)
Thread.start do
d6 = TCPserver.open("::", dport6).accept
d4 = TCPsocket.open(s4.getpeer[3], dport4)
t = []
t[0] = Thread.start do
tcpcopy(d6, d4)
end
t[1] = Thread.start do
tcpcopy(d4, d6)
end
for i in t
i.join
end
d4.close
d6.close
end
end
def ftp_parse_2428(line)
if (line[0] != line[line.length - 1])
return nil
end
t = line.split(line[0 .. 0]) # as string
if (t.size != 4 || t[1] !~ /^[12]$/ || t[3] !~ /^\d+$/)
return nil
end
return t[1 .. 3]
end
def relay_ftp_command(s6, s4, state)
STDERR.print "relay_ftp_command start\n" if DEBUG
while TRUE
begin
STDERR.print "s6.gets\n" if DEBUG
line = s6.gets
STDERR.print "line is #{line}\n" if DEBUG
if line == nil
return nil
end
# translate then copy
STDERR.print "line is #{line}\n" if DEBUG
if (line =~ /^EPSV\r\n/i)
STDERR.print "EPSV -> PASV\n" if DEBUG
line = "PASV\n"
state = "EPSV"
elsif (line =~ /^EPRT\s+(.+)\r\n/i)
t = ftp_parse_2428($1)
if t == nil
s6.puts "501 illegal parameter to EPRT\r\n"
next
end
# some tricks should be here
s6.puts "501 illegal parameter to EPRT\r\n"
next
end
STDERR.print "fail: send #{line} as is\n" if DEBUG
s4.puts(line)
break
rescue EOFError
return nil
rescue IOError
return nil
end
end
STDERR.print "relay_ftp_command finish\n" if DEBUG
return state
end
def relay_ftp_status(s4, s6, state)
STDERR.print "relay_ftp_status start\n" if DEBUG
while TRUE
begin
line = s4.gets
if line == nil
return nil
end
# translate then copy
s6.puts(line)
next if line =~ /^\d\d\d-/
next if line !~ /^\d/
# special post-processing
case line
when /^221 / # result to QUIT
s4.shutdown(0)
s6.shutdown(1)
end
break if (line =~ /^\d\d\d /)
rescue EOFError
return nil
rescue IOError
return nil
end
end
STDERR.print "relay_ftp_status finish\n" if DEBUG
return state
end
def relay_ftp(sock, name)
STDERR.print "relay_ftp(#{sock}, #{name})\n" if DEBUG
while TRUE
STDERR.print "relay_ftp(#{sock}, #{name}) accepting\n" if DEBUG
s = sock.accept
STDERR.print "relay_ftp(#{sock}, #{name}) accepted #{s}\n" if DEBUG
Thread.start do
threads = []
STDERR.print "accepted #{s} -> #{Thread.current}\n" if DEBUG
s6 = s
dest6 = s.addr[3]
if !DEBUG_LOOPBACK
t = s.getsockname.unpack("x8 x12 C4")
dest4 = "#{t[0]}.#{t[1]}.#{t[2]}.#{t[3]}"
port4 = s.addr[1]
else
dest4 = "127.0.0.1"
port4 = "ftp"
end
if DEBUG
STDERR.print "IPv6 dest: #{dest6} IPv4 dest: #{dest4}\n" if DEBUG
end
STDERR.print "connect to #{dest4} #{port4}\n" if DEBUG
s4 = TCPsocket.open(dest4, port4)
STDERR.print "connected to #{dest4} #{port4}, #{s4.addr[1]}\n" if DEBUG
state = 0
while TRUE
# translate status line
state = relay_ftp_status(s4, s6, state)
break if state == nil
# translate command line
state = relay_ftp_command(s6, s4, state)
break if state == nil
end
STDERR.print "relay_ftp(#{sock}, #{name}) closing s4\n" if DEBUG
s4.close
STDERR.print "relay_ftp(#{sock}, #{name}) closing s6\n" if DEBUG
s6.close
STDERR.print "relay_ftp(#{sock}, #{name}) done\n" if DEBUG
end
end
STDERR.print "relay_ftp(#{sock}, #{name}) finished\n" if DEBUG
end
def relay_tcp(sock, name)
STDERR.print "relay_tcp(#{sock}, #{name})\n" if DEBUG
while TRUE
STDERR.print "relay_tcp(#{sock}, #{name}) accepting\n" if DEBUG
s = sock.accept
STDERR.print "relay_tcp(#{sock}, #{name}) accepted #{s}\n" if DEBUG
Thread.start do
threads = []
STDERR.print "accepted #{s} -> #{Thread.current}\n" if DEBUG
s6 = s
dest6 = s.addr[3]
if !DEBUG_LOOPBACK
t = s.getsockname.unpack("x8 x12 C4")
dest4 = "#{t[0]}.#{t[1]}.#{t[2]}.#{t[3]}"
port4 = s.addr[1]
else
dest4 = "127.0.0.1"
port4 = "telnet"
end
if DEBUG
STDERR.print "IPv6 dest: #{dest6} IPv4 dest: #{dest4}\n" if DEBUG
end
STDERR.print "connect to #{dest4} #{port4}\n" if DEBUG
s4 = TCPsocket.open(dest4, port4)
STDERR.print "connected to #{dest4} #{port4}, #{s4.addr[1]}\n" if DEBUG
[0, 1].each do |i|
threads[i] = Thread.start do
if (i == 0)
tcpcopy(s6, s4)
else
tcpcopy(s4, s6)
end
end
end
STDERR.print "relay_tcp(#{sock}, #{name}) wait\n" if DEBUG
for i in threads
STDERR.print "relay_tcp(#{sock}, #{name}) wait #{i}\n" if DEBUG
i.join
STDERR.print "relay_tcp(#{sock}, #{name}) wait #{i} done\n" if DEBUG
end
STDERR.print "relay_tcp(#{sock}, #{name}) closing s4\n" if DEBUG
s4.close
STDERR.print "relay_tcp(#{sock}, #{name}) closing s6\n" if DEBUG
s6.close
STDERR.print "relay_tcp(#{sock}, #{name}) done\n" if DEBUG
end
end
STDERR.print "relay_tcp(#{sock}, #{name}) finished\n" if DEBUG
end
def usage()
STDERR.print "usage: #{$0} [-f] port...\n"
end
#------------------------------------------------------------
$mode = "tcp"
while ARGV[0] =~ /^-/ do
case ARGV[0]
when /^-f/
$mode = "ftp"
else
usage()
exit 0
end
ARGV.shift
end
if ARGV.length == 0
usage()
exit 1
end
ftpport = Socket.getservbyname("ftp")
res = []
for port in ARGV
t = Socket.getaddrinfo(nil, port, Socket::PF_INET6, Socket::SOCK_STREAM,
nil, Socket::AI_PASSIVE)
if (t.size <= 0)
STDERR.print "FATAL: getaddrinfo failed (port=#{port})\n"
exit 1
end
res += t
end
sockpool = []
names = []
listenthreads = []
res.each do |i|
s = TCPserver.new(i[3], i[1])
n = Socket.getnameinfo(s.getsockname, Socket::NI_NUMERICHOST|Socket::NI_NUMERICSERV).join(" port ")
if i[6] == IPPROTO_IPV6
s.setsockopt(i[6], IPV6_FAITH, 1)
end
s.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1)
sockpool.push s
names.push n
end
if DEBUG
(0 .. sockpool.size - 1).each do |i|
STDERR.print "listen[#{i}]: #{sockpool[i]} #{names[i]}\n" if DEBUG
end
end
(0 .. sockpool.size - 1).each do |i|
listenthreads[i] = Thread.start do
if DEBUG
STDERR.print "listen[#{i}]: thread #{Thread.current}\n" if DEBUG
end
STDERR.print "listen[#{i}]: thread #{Thread.current}\n" if DEBUG
case $mode
when "tcp"
relay_tcp(sockpool[i], names[i])
when "ftp"
relay_ftp(sockpool[i], names[i])
end
end
end
for i in listenthreads
i.join
end
exit 0

View File

@ -69,7 +69,7 @@ __FBSDID("$FreeBSD$");
* 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
@ -1305,14 +1305,6 @@ setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on))
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
@ -1744,15 +1736,15 @@ getconfigent(void)
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);
}