#!/bin/bash
#
# Configures the 6to4 address based on the ip address of the interface to which
# the default route points.
# Parameter 1: action (start, stop, restart)
#           2: interface SLA (optional)
#           3: interface ID (optional)
#           4: interface prefix (optional)
#           5: IPv6 relay address (optional)
#

# Variable parameters. TUN_INTF used for start and stop, all others only start
# No validation of input at all!!
TUN_INTF=${2:-tun6to4}
SLA_INTF=${3:-0}
INTF_ID=${4:-1}
INTF_PFX=${5:-64}
TUN_RELY=${6:-192.88.99.1}

case "${1}" in
    start)
        # Clean up before configuring the tunnel
        $0 stop ${TUN_INTF}

        # IPv6 ready?
        [ -f /proc/net/if_inet6 ] || exit 0

        # Grab the device of the default route (may be
        # multiple -> CUR_DV is an array)
        CUR_DV=(`ip -4 route list | awk '/^default / { print $0 }' | \
                                    sed 's/.* dev \([^ ]\+\).*$/\1/'`)

        # Is there any device? Or no default route at all??
        if [ -z ${CUR_DV} ]; then
            echo "No default route. Cannot determine IPv4 address to use"
            exit 0
        fi

        # We simply take the device from the first default route
        CUR_IP=(`ip -4 addr show ${CUR_DV} | awk '/inet / { print $2 }' | \
               sed -e 's/^\(\([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}\).*$/\1/'`)

        # Find the MTU on the interface used for the tunnel
        DEV_MTU=`ip link show ${CUR_DV} | tr '\n' ' ' | \
                                          sed 's/.* mtu \([0-9]\+\).*$/\1/'`

        # Multiple IP addresses may be defined on device. First one is ours.
        # Add the tunnel. The local address is the one found from default route.
        ip tunnel add ${TUN_INTF} mode sit remote any local ${CUR_IP}
        # Bring the tunnel up.
        ip link set dev ${TUN_INTF} mtu `expr ${DEV_MTU} - 20` up
        # Add the interface address
        IPV6_ADDR=$(printf "2002:%02x%02x:%02x%02x:%04x::%04x" \
                  $(echo "${CUR_IP} ${SLA_INTF} ${INTF_ID}" | tr '.' ' '))
        ip -6 addr add ${IPV6_ADDR}/${INTF_PFX} dev ${TUN_INTF}

        # Add the routes
        ip -6 route add 2002::/16 dev ${TUN_INTF}
        ip -6 route add ::/0 via ::${TUN_RELY} dev ${TUN_INTF} metric 1

        # Notify
        echo "6to4 tunnel '${TUN_INTF}' created." \
             "IPv6 address: ${IPV6_ADDR}/${INTF_PFX}, IPv6 relay: ${TUN_RELY}"
        ;;
    stop)
        # Skip if device is not configured
        ip link list ${TUN_INTF} > /dev/null 2>&1
        if [ $? = 0 ]; then
            # Remove all routes going through this device
            ip -6 route flush dev ${TUN_INTF}
            # Disable the link
            ip link set dev ${TUN_INTF} down
            # Delete the device
            ip tunnel del ${TUN_INTF}
            # Notify
            echo "6to4 tunnel '${TUN_INTF}' removed."
        fi
        ;;
    restart)
        $0 stop ${2}
        $0 start ${2} ${3} ${4} ${5}
        ;;
    *)
        echo "Usage: `basename $0` (start|restart)" \
             "[<tunnel-name> [<sla> [<int-id> [<prefix> [<relay-ip>]]]]]"
        echo "       `basename $0` stop [<tunnel-name>]"
        ;;
esac

