#!/bin/bash
# Filename:      grml-vnet
# Purpose:       program to create tun/tap devices and add them to a bridge
# Authors:       Michael Gebetsroither <gebi@grml.org>
# Bug-Reports:   see http://grml.org/bugs/
# License:       This file is licensed under the GPL v2.
################################################################################

set -e
#set -x

PN_="`basename $0`"
OPT_DEL_='false'
OPT_USER_=''
OPT_GROUP_=''
OPT_BRIDGE_=''
OPT_AUTO_='false'


function printUsage()
{
    cat <<EOT
Usage: "$PN_" [OPTIONS] <tun0> <tun1> ...

$PN_ creates persistent tun/tap devices with bridge handling

OPTIONS:
   -d             delete the tun devices and remove them from the bridge if given
   -u <user>      this user should be able to use the tun device
   -g <group>     this group should be able to use the tun device
   -b <bridge>    if given, all tun/tap devices are added/removed from the bridge
   -a             enable auto mode, eg. create the bridge if not already existing and
                  delete it when empty after removing given tun devices
   -h             this help
EOT
}

function fromCmdline()
{
    local action_="$1"
    shift

    while (( $# != 0 )); do
        case "$1" in
            "") continue ;;
        esac
        $action_ "$1"
        shift
    done
}

function createTun()
{
    local args_=''
    if [[ $OPT_USER_ != '' ]]; then args_="$args_ -u $OPT_USER_"; fi
    if [[ $OPT_GROUP_ != '' ]]; then args_="$args_ -u $OPT_GROUP_"; fi
    tunctl -t "$1" $args_
    if [[ $OPT_BRIDGE_ != '' ]]; then
        brctl addif "$OPT_BRIDGE_" "$1"
    fi
    ip link set up dev "$1"
}

function trashTun()
{
    ip link set down dev "$1"
    if [[ $OPT_BRIDGE_ != '' ]]; then
        brctl delif "$OPT_BRIDGE_" "$1"
    fi
    tunctl -d "$1"
}

function die()
{
    echo "$@" >&2
    exit 1
}

##
# MAIN
##

while getopts "du:g:b:ah" opt; do
    case "$opt" in
        d) OPT_DEL_='true' ;;
        u) OPT_USER_="$OPTARG" ;;
        g) OPT_GROUP_="$OPTARG" ;;
        b) OPT_BRIDGE_="$OPTARG" ;;
        a) OPT_AUTO_='true' ;;
        h) printUsage; exit 0 ;;
        ?) printUsage; exit 1 ;;
    esac
done
shift $(($OPTIND - 1))

if [[ $OPT_DEL_ == 'false' ]]; then
    if [[ $OPT_BRIDGE_ != '' && $OPT_AUTO_ == 'true' ]]; then
        brctl showmacs "$OPT_BRIDGE_" &>/dev/null || brctl addbr "$OPT_BRIDGE_"
        ip link set up dev "$OPT_BRIDGE_"
    fi
    fromCmdline "createTun" "$@"
else
    fromCmdline "trashTun" "$@"
    if [[ $OPT_BRIDGE_ != '' && $OPT_AUTO_ == 'true' ]]; then
        tmp_="`brctl showmacs "$OPT_BRIDGE_" |wc -l`"
        if (( $tmp_ == 1 )); then
            ip link set down dev "$OPT_BRIDGE_"
            brctl delbr "$OPT_BRIDGE_"
        else
            die "E: bridge $OPT_BRIDGE_ not empty, not removing"
        fi
    fi
fi

## END OF FILE #################################################################
