#! /bin/sh
# $Header:$

# Environment:
#  IFACE        = Logical interface name
#  MODE         = { start | stop }
#  METHOD       = manual, otherwise exit
#  ADDRFAM      = inet, otherwise exit
#  IF_DEVICE    = physical interface name (defaults to logical)
#  IF_MASTER    = master interface (optional)
#  IF_MAC       = mac of the master interface
#  IF_VLAN_ID   = VLAN id

. /etc/network/if.d/common-functions

# remove state if interface is being stopped

if [ "$MODE" = 'stop' ]; then
    DEV=`state_entry vlan-dev`
    if [ -n "$DEV" ]; then
        # we have a vlanned interface
        if ! /sbin/ip addr show dev $DEV | grep -s -q inet; then
          exec_down "vlan" "vconfig"
        fi
    fi
    exec_down "vlan" ""
    exec_down "vlan-mac" ""
    exec_down "vlan-master" ""
    exec_down "vlan-id" ""
    exec_down "vlan-dev" ""
    exit 0
fi

[ "$MODE" = 'start' ] || exit 0

# check if vlan needs to be configured
[ "$IF_VLAN_ID" -ne 0 ] || exit 0

# check if vlans are supported
if [ "$VLAN_SUPPORT" != 'yes' ]; then
  abort "No VLAN support in kernel"
fi

# check if encapsulation is correct

verbose "encapsulation $IF_ENCAPSULATION"
if [ "$IF_ENCAPSULATION" != "dot1q" ]; then
  abort "invalid encapsulation $IF_ENCAPSULATION"
fi

# find master interface
if [ -z "$IF_MASTER" -a -z "$IF_MAC" ]; then
    abort "no master configured for VLAN interface $IFACE"
fi

if [ -n "$IF_MASTER" ]; then
    # master by name
    # resolve master to a physical device
    IF_MASTER_DEV=`dev_state_entry "$IF_MASTER" dev`
    [ -z "$IF_MASTER_DEV" ] && IF_MASTER_DEV="$IF_MASTER"
    if ! if_exists "$IF_MASTER_DEV"; then
        abort "master $IF_MASTER for VLAN interface $IFACE does not exist"
    fi
    IF_MAC=`get_if_mac "$IF_MASTER_DEV"`
    if [ -z "$IF_MAC" ]; then
        abort "master $IF_MASTER for $IFACE is no ethernet device"
    fi
    IF_MASTER="$IF_MASTER_DEV"
else
    # master by mac
    for iface in `list_ifaces`; do
        if [ "`get_if_mac "$iface"`" = "$IF_MAC" ]; then
            IF_MASTER="$iface"
            break
        fi
    done
    if [ -z "$IF_MASTER" ]; then
        abort "no master with MAC $IF_MAC found for $IFACE"
    fi
fi

# IF_MASTER and IF_MAC are set and valid now

# check if VLAN already exists
vlan=`find_vlan "$IF_MASTER" $IF_VLAN_ID`
verbose "find_vlan $IF_MASTER $IF_VLAN_ID = $vlan"
if [ -n "$vlan" ]; then
    # VLAN exists, check if it's the one we want
    for iface in `list_if_by_state dev "^$vlan[ \t]*\$"`; do
    	verbose "test $iface"
        if [ "$iface" != "$IFACE" -a "$vlan" != "$IF_DEVICE" ]; then
            abort "device $IF_MASTER VLAN $IF_VLAN_ID already up as $vlan for $iface"
        fi
    done
    # it's the one we want
    newif="$vlan"
else
    # create new vlan
    verbose "vconfig add \"$IF_MASTER\" $IF_VLAN_ID"
    vconfig add "$IF_MASTER" $IF_VLAN_ID >/dev/null
    newif=`find_vlan "$IF_MASTER" $IF_VLAN_ID`
    if [ -z "$newif" ]; then
        abort "could not add VLAN $IF_VLAN_ID on $IF_MASTER for $IFACE"
    fi
fi

# newif is set to the VLAN interface

# rename the interface if necessary
if [ "$newif" != "$IF_DEVICE" ]; then
    verbose "ip link set dev \"$newif\" down"
    ip link set dev "$newif" down
    verbose "ip link set dev \"$newif\" name \"$IF_DEVICE\""
    ip link set dev "$newif" name "$IF_DEVICE"
fi

# ensure that master is up
if ! is_if_up "$IF_MASTER"; then
    verbose "ip link set dev \"$IF_MASTER\" up"
    ip link set dev "$IF_MASTER" up
fi

add_down "vlan-id" "$IF_VLAN_ID"
add_down "vlan-master" "$IF_MASTER"
add_down "vlan-mac" "$IF_MAC"
add_down "vlan-dev" "$IF_DEVICE"
add_down "vlan" "rem \"$IF_DEVICE\" >/dev/null"

# vi:sw=4 
# end of file
