#!/bin/bash

# Based on: http://www.uibk.ac.at/linuxdoc/LDP/HOWTO/Linux+IPv6-HOWTO/configuring-ipv6to4-tunnels.html
#
# Uses the first available 6to4 relay (::192.88.99.1).
#
# Also adjust /etc/gai.conf if you want to enforce IPv6 preference (precedence).
# One way to do this (in Ubuntu 10.04) would be to disable (comment out) all the lines and
#   add this: (without the comment sign of course)
#
#   label 2000::/3       0
#
# Note that gai.conf should be read by glibc, so there's no need to reboot or so. However, depending on the situation
#   you may need to restart your application to get the changes to take effect.
#
# You can also test this by means of a C program (which, at least for its own purposes re-reads gai.conf implicitly), found on:
#   http://linux-hacks.blogspot.com/2008/04/default-address-selection-part-1.html
#
# Invoke it with a hostname that maps to both IPv4 and IPv6 to see their relative priority (addresses with higher priority are listed first).

DEV="eth0"
IPV4_ADDRESS=`ifconfig $DEV | grep "inet addr" | sed 's/Bcast.*//' | sed 's/.*inet addr://'`
IPV4_ADDRESS_REFORMATTED="`echo $IPV4_ADDRESS | tr '.' ' '`"
OUR_IPV6_GW=`printf "2002:%02x%02x:%02x%02x::1" $IPV4_ADDRESS_REFORMATTED`

TTL=30 # TODO what's a good setting here?

function start_tunnel
{
  /sbin/ip tunnel add tun6to4 mode sit ttl $TTL remote any local $IPV4_ADDRESS
  /sbin/ip link set dev tun6to4 up
  /sbin/ip -6 addr add $OUR_IPV6_GW/16 dev tun6to4
  /sbin/ip -6 route add 2000::/3 via ::192.88.99.1 dev tun6to4 metric 1

  # /sbin/ip -6 route add 2000::/3 via 2002:c058:6301::1 dev tun6to4 metric 1 # this may be needed instead of the previous line on some OSes
}

function stop_tunnel
{
  /sbin/ip -6 route flush dev tun6to4
  /sbin/ip link set dev tun6to4 down
  /sbin/ip tunnel del tun6to4
}

function show_invocation
{
  echo "Invocation: $0 [start|stop]"
  exit 0
}

if [ $# -ne 1 ]
then
  show_invocation
fi

ARG=$1

case "$ARG" in
  start)
    echo "Starting."
    start_tunnel
    ;;
  stop)
    echo "Stopping."
    stop_tunnel
    ;;
  *)
    show_invocation
    ;;
esac
