
This is the alpha version of my IP tunneling driver.

Protocol Tunneling:

	A network tunneling driver encapsulates packets of one 
protocol type within packets of another protocol type.  It sends
them out over the network to a relay (or destination) where the
packet is unwrapped and is forwarded to it's ultimate destination.
Packet tunneling is useful in situations where you want to route
packets of a non-standard protocol type over the common network.
A good example of this is 'IPX encapsulation', in which IPX packets
from a DOS network are routed across an IP network by encapsulating
them in IP packets.

	There are two parts to every protocol tunnel.  There is
the encapsulator, and the decapsulator.  The encapsulator wraps
the packets in the host protocol and sends them on their way,
while the decapsulator takes wrapped packets at the other end
and unwraps them and forwards them (or whatever else should be
done with them.)

	IP tunneling is a specific case of protocol tunneling,
in which the encapsulating protocol is IP, and the encapsulated
protocol may be any other protocol, including Apple-Talk, IPX,
or even IP within IP.

	For more information on the semantics and specifications
of IP encapsulation, see RFC-1241, also included in this package.


My Implementation:

	My implementation of IP tunneling for Linux consists
of two loadable module drivers, one an encapsulator (tunnel.o)
and the other a decapsulator (ipip.o).  Both are used for
setting up a working IP-in-IP tunnel.  Currently, the drivers
only support IP encapsulated in IP.

	The tunnel driver is implemented as a network device,
based on the Linux loopback driver written (in part) by Ross Biro,
Fred N. van Kempen, and Donald Becker.  After the driver is 
loaded, it can be set up as any other network interface, using 
ifconfig.  The tunnel device is given it's own IP address, which
can match that of the machine, and also is given a pointopoint
address.  This pointopoint address is the address of the machine
providing the decapsulating endpoint for the IP tunnel.  After
the device is configured for use, the 'route' command can be used
to route traffic through the IP tunnel.  There must be a route to
the decapsulating endpoint that does not go through the tunnel
device, otherwise a looping tunnel is created, preventing the 
network traffic from leaving the local endpoint.

	The decapsulating endpoint must have loaded the ipip.o
decapsulator module for it to understand IP-in-IP encapsulation.
This module takes any IP-in-IP packet that is destined for the local
machine, unwraps it, and sends it on it's way, using standard 
routing rules.  The current implementation of IP decapsulation does
no checking on the packet, other than making sure wrapper is bound
for the local machine.

	Note that the above setup only provides a one-way pipe.
To provide a full two-way IP tunnel, the decapsulation host must
set up an IP encapsulation driver, and the encapsulating host must
load the IP decapsulation module, providing full duplex communication
through the IP tunnel.

An example setup might be as follows.

	Machine A has an ethernet interface with an IP address 
of 111.112.101.37, while machine B is on a different network, with
an ethernet interface at IP address 111.112.100.86.  For some 
reason, machine A needs to appear on machine B's network.  It could
do that by setting up an IP tunnel with machine B.

First, the commands that would be run on machine A:
(Assuming both machines are Linux hosts, running Linux 1.1.x)

# insmod ipip.o ; insmod tunnel.o          // Here the drivers are loaded.
# ifconfig tunl 111.112.100.87 pointopoint 111.112.100.86
# ifconfig tunl netmask 255.255.255.0      // Set a proper netmask.
# route add 111.112.100.86 dev eth0        // Set a static route to B.
# route add -net 111.112.100.0 dev tunl    // Set up other routes.

At this point, machine A is ready to route all traffic to the
network that machine B resides on.  But now, machine B needs to
set up its half of the IP tunnel:

# insmod ipip.o ; insmod tunnel.o          // Here the drivers are loaded.
# ifconfig tunl 111.112.100.86 pointopoint 111.112.101.37
# ifconfig tunl netmask 255.255.255.0      // Set a proper netmask.
# route add 111.112.100.87 dev eth0        // Set a static route to B.
# arp -s 111.112.100.87 EE.EE.EE.EE.EE pub // Act as a proxy arp server.

The extra step of "arp -s" is needed so that when machines on 
network B query to see if 111.112.100.87 (the "ghost" host)
exists, machine B will respond, acting as an arp proxy for machine
A.  In the command line, EE.EE.EE.EE.EE should be replaced with
the ethernet hardware address of machine B's ethernet card.

Notice that machine B's setup is almost the inverse of machine A's
setup.  This is because IP tunneling is a peer-to-peer concept.  
There is no client and no server, there is no state to keep track
of.  The concept is simple.  Every IP packet outbound through the
tunnel interface is wrapped and sent to the pointopoint address
and every incoming IP-in-IP packet bound for the local machine is
unwrapped and re-routed normally.
The only difference in the two machines setup shown above is that 
machine A set it's tunnel address to one existing on machine B's
network, while B set a route to machine A's tunnel device address
through the tunnel.  This is because machine A wants to have a new
address on network B, and machine B is simply acting as a proxy 
for machine A.  Machine A needs it's tunnel address to be on network 
B so that when packets from machine B are unwrapped, the Linux 
routing system knows that the address is a local one.  Due to a 
feature of Linux, any packets recieved locally, bound for another
local address, are simply routed through the loopback interface.
This means that the tunnel device should never recieve packets.  Even
on machine B, it is the ethernet interface that is receiving wrapped
packets, and once they are unwrapped they go back out the ethernet
interface.  This could cause Linux to generate ICMP redirect messages
if this special routing case isn't caught (see /linux/net/inet/ip.c)

