#! /bin/bash
# $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/ifupdown-scripts-zg2.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 ! has_ip_address $DEV; then
            exec_down "vlan" "vconfig"
            IF_MASTER_DEV=$(state_entry vlan-master)
	    if ! is_active_vlan_master "$IF_MASTER_DEV" && ! has_ip_address "$IF_MASTER_DEV"; then
	        ip link set dev $IF_MASTER_DEV down
	    fi
        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 ! is_vlan_slave $iface; then
            if [ "$(get_if_mac "$iface")" = "$IF_MAC" ]; then
                IF_MASTER="$iface"
                break
	    fi
        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

# 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

# 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

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
