###############################################################################
# Interface activation/deactivation functions
#  Here so that special interface commands can be called and daemons started
#  
#  Arps can be set up here, network/host routes and so forth.
#
#  This appears to be a little messy but is needed to achieve maximum 
#  functionality and flexibility.
#
###############################################################################

SED_IFSTR='s/\([-A-Za-z]*\)[0-9]*$/\1/'
SED_IPV4STR='s/^.*inet \([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+[/0-9]\+\) .*$/\1/'
SED_IPV6STR='s/^.*inet6 \([0-9a-f]\+\:.*\:[0-9a-f]\+[/0-9]\+\) .*$/\1/'
SED_IPV6ADDR="sed -e 's/:0\+\([0-9a-fA-F]\+\)/:\1/g' | sed -e 's/^0\+\([0-9a-fA-F]\+\)/\1/'| sed -e 's/\(:0\)\+:\(:0\)*\|\(:0\)*:\(:0\)\+/:/'"
SED_IPV4ADDR="sed -e 's/\.0\+\([0-9a-fA-F]\+\)/.\1/g' | sed -e 's/^0\+\([0-9a-fA-F]\+\)/\1/'"

if_addr_start () {
	local IPADDR2 ADDR ADDR2
	local ADDRS
	local ANS
	local OIFS
	local IFACE=$1

	# Glue stuff
	if [ -n "$MASKLEN" ]; then
		IPADDR="${IPADDR}/${MASKLEN}"
	fi

	if [ -n "$PTPADDR" ]; then
		IPADDR="${IPADDR}_peer_${PTPADDR}"
	fi

	if [ -n "$BROADCAST" ]; then
		IPADDR="${IPADDR}_brd_${BROADCAST}"
	fi

	if [ -n "$IP_EXTRA_ADDRS" ]; then
		IPADDR="$IPADDR $IP_EXTRA_ADDRS"
	fi

	# Take care of leading zeroes in supplied addresses
	for ADDR in $IPADDR; do
		if echo $ADDR | grep -q ':'; then
			#IPv6
			ADDR2=`echo $ADDR | eval $SED_IPV6ADDR` 	
			IPADDR2="$IPADDR2 $ADDR2"
		else
			#IPv4
			ADDR2=`echo $ADDR | eval $SED_IPV4ADDR`
			IPADDR2="$IPADDR2 $ADDR2"
		fi
	done
	IPADDR="$IPADDR2"

	# Set up link MTU etc
	ip link set $1 $IFCFG_MULTICAST $IFCFG_MTU
	
	# Set up IPv6 Interface sysctl here before interface goes up
	ifv6_setproc $1 accept_redirects $IPV6_ACCEPT_REDIRECTS
	ifv6_setproc $1 accept_ra $IPV6_ACCEPT_RA
	ifv6_setproc $1 accept_ra_pinfo $IPV6_ACCEPT_RA_PINFO
	ifv6_setproc $1 accept_ra_rt_info_max_plen $IPV6_ACCEPT_RA_RT_INFO_MAX_PLEN
	ifv6_setproc $1 disable_ipv6 $IPV6_DISABLE
	ifv6_setproc $1 forwarding $IPV6_FWDING
	ifv6_setproc $1 router_solicitations $IPV6_ROUTER_SOLICITATIONS
	ifv6_setproc $1 use_tempaddr $IPV6_PRIVACY
	
	# Bring the interface up
	ip link set dev $1 up

	# This one has to be set after interface up
	ifv6_setproc $1 mtu $IPV6_MTU

	# Set up the addresses on the interface
	
	ADDRS=`ip addr show dev $IFACE |  grep '^.*inet[ 46]' \
		| sed -e "$SED_IPV4STR" | sed -e "$SED_IPV6STR"`

	for ADDR in $IPADDR; do
		for ADDR2 in $ADDRS; do
			ADDR2=`echo $ADDR2 | sed -e 's/\/32\|\/128//'`
			ANS=${ADDR#$ADDR2}
			if [ "$ANS" != "$ADDR" ]; then
				continue 2
			fi
		done
		OIFS=$IFS
		IFS="${IFS}_"
		ip addr add $ADDR dev $IFACE
		IFS=$OIFS
	done
	
	# Strip out addresses that should not be there
	for ADDR in $ADDRS; do
		# Don't delete IPv6 link local addresses
		if echo $ADDR | grep -q -i '^fe[89ab]'; then
			continue
		fi
		ANS=`echo $IPADDR | grep $ADDR`
		if [ -z "$ANS" ]; then
			ip addr del $ADDR dev $IFACE
		fi
	done

	return 0
}


if_addr_stop () {
	local FILE
	
	qt ip link set $1 down
	qt ip addr flush dev $1		
}

if_up () {
	local ADDR
	local IF_NODASH=`echo "$1" | sed -e 's/\-/_/g'`

        # sort out a few things to make life easier - here so that you
        # can see what is done and so that you can add anything if needed
        eval IPADDR=\${"${IF_NODASH}"_IPADDR:-""}     # I am also a good genius
	eval MASKLEN=\${"${IF_NODASH}"_MASKLEN:-""}
	eval BROADCAST=\${"${IF_NODASH}"_BROADCAST:-""}
        eval PTPADDR=\${"${IF_NODASH}"_PTPADDR:-""}
        eval IP_EXTRA_ADDRS=\${"${IF_NODASH}"_IP_EXTRA_ADDRS:-""}
        eval MTU=\${"${IF_NODASH}"_MTU:-""}
        eval MULTICAST=\${"${IF_NODASH}"_MULTICAST:-""}
	eval HB_TICKLE=\${"${IF_NODASH}"_HB_TICKLE:-""}
	eval BRIDGE=\${"${IF_NODASH}"_BRIDGE:-""}
	eval RESOLVCONF=\${"${IF_NODASH}"_RESOLVCONF:-""}
	eval local DEFAULT_GW=\${"${IF_NODASH}"_DEFAULT_GW:-""}
        eval local FAIRQ=\${"${IF_NODASH}"_FAIRQ:-""}
        eval local TXQLEN=\${"${IF_NODASH}"_TXQLEN:-""}
        eval local IP_SPOOF=\${"${IF_NODASH}"_IP_SPOOF:-""}
        eval local IP_KRNL_LOGMARTIANS=\${"${IF_NODASH}"_IP_KRNL_LOGMARTIANS:-""}
        eval local IP_SHARED_MEDIA=\${"${IF_NODASH}"_IP_SHARED_MEDIA:-""}
        eval local IP_SEND_REDIRECTS=\${"${IF_NODASH}"_IP_SEND_REDIRECTS:-""}
        eval local PROXY_ARP=\${"${IF_NODASH}"_PROXY_ARP:-""}
	eval IPV6_ACCEPT_REDIRECTS=\${"${IF_NODASH}"_IPV6_ACCEPT_REDIRECTS:-""}
	eval IPV6_ACCEPT_RA=\${"${IF_NODASH}"_IPV6_ACCEPT_RA:-""}
	eval IPV6_ACCEPT_RA_PINFO=\${"${IF_NODASH}"_IPV6_ACCEPT_RA_PINFO:-""}
	eval IPV6_ACCEPT_RA_RT_INFO_MAX_PLEN=\${"${IF_NODASH}"_IPV6_ACCEPT_RA_RT_INFO_MAX_PLEN:-""}
	eval IPV6_DISABLE=\${"${IF_NODASH}"_IPV6_DISABLE:-""}
	eval IPV6_FWDING=\${"${IF_NODASH}"_IPV6_FWDING:-""}
	eval IPV6_PRIVACY=\${"${IF_NODASH}"_IPV6_PRIVACY:-""}
	eval IPV6_ROUTER_SOLICITATIONS=\${"${IF_NODASH}"_IPV6_ROUTER_SOLICITATIONS:-""}
	eval IPV6_MTU=\${"${IF_NODASH}"_IPV6_MTU:-""}
	if [ -n "DEFAULT_GW" -a -z "$IPV4_DEFAULT_GW" ]; then
		IPV4_DEFAULT_GW="$DEFAULT_GW"
		IPV4_DEFAULT_GWDEV="$1"
	fi
	unset IFCFG_BROADCAST IFCFG_MULTICAST IFCFG_MTU
	if [ -n "$BROADCAST" ] ; then
                IFCFG_BROADCAST="broadcast $BROADCAST"
        fi
	if [ -n "$MTU" ] ; then
		IFCFG_MTU="mtu $MTU"
	fi
	if [ -n "$MULTICAST" ] ; then
		case $MULTICAST in
		No|no|NO|off|Off|OFF)
			IFCFG_MULTICAST="multicast off"
			;;
		Yes|YES|yes|on|On|ON)
			IFCFG_MULTICAST="multicast on"
			;;
		*)
			unset IFCFG_MUTLICAST
			;;
		esac
	fi
	local IFTYPE=`echo $1 | sed -e $SED_IFSTR`
	local IFTYPE_NODASH=`echo "$IFTYPE" | sed -e 's/\-/_/g'`

	# Do dee global bridge stuff
	brg_global
		 
	# Set default interface flags here - used for PPP and WAN interfaces
        # IPv4
	ifv4_setproc default rp_filter $DEF_IP_SPOOF
        ifv4_setproc default log_martians $DEF_IP_KRNL_LOGMARTIANS
	ifv4_setproc all accept_redirects $ALLIF_ACCEPT_REDIRECTS

        # Set up each interface
	if qt type ${IF_NODASH}_start ; then
		# execute user supplied individual interface start up
		${IF_NODASH}_start $1
	elif qt type ${IFTYPE_NODASH}_start ; then
		# execute user supplied typed interface start up
		${IFTYPE_NODASH}_start $1
	else
		# default interface startup
                brg_iface $1 up "$BRIDGE" "$IPV6_DISABLE"
		# Start interface
		if_addr_start $1
	fi
        
	# Do universal interface config items here
	# QoS setup
	ip_QoSclear $1
	ip_QoS $1
        # Set the TX Queue Length
        [ -n "$TXQLEN" ] \
                && ip link set $1 txqlen $TXQLEN
	
	# Default route support
	ipv4_default_route $1
	ipv6_default_route $1

	# Set up routes and ARP etc
	if qt type ${IF_NODASH}_network ; then
		${IF_NODASH}_network $1
	fi

	# Resolvconf support
	if [ -n "$RESOLVCONF" ]; then
		if_resolvconf_up $1 "$RESOLVCONF"
	fi

	# Interface sysctl stuff here
	# IPv4
	# Spoof protection
        ifv4_setproc $1 rp_filter $IP_SPOOF
        # Kernel logging of martians on this interface
        ifv4_setproc $1 log_martians $IP_KRNL_LOGMARTIANS
	# Shared Media stuff
	ifv4_setproc $1 shared_media $IP_SHARED_MEDIA
	# Sending of Redirects
	ifv4_setproc $1 send_redirects $IP_SEND_REDIRECTS
	# Proxy ARP support
	ifv4_setproc $1 proxy_arp $PROXY_ARP

	# Emit required upstart event - this can be adjusted
	iface_upstart_emit 'net-device-up' "IFACE=${1}" 'LOGICAL=${1}' \
				'ADDRFAM=inet' 'METHOD=static'

	unset IPADDR MASKLEN BROADCAST PTPADDR IP_EXTRA_ADDRS MTU MULTICAST
	unset BROADCAST RESOLVCONF
	unset IPV6_ACCEPT_REDIRECTS IPV6_ACCEPT_RA IPV6_FWDING IPV6_MTU 
	unset IPV6_ROUTER_SOLICITATIONS IPV6_PRIVACY IPV6_ACCEPT_RA_PINFO 
	unset IPV6_DISABLE
	unset IFCFG_BROADCAST IFCFG_MULTICAST IFCFG_MTU

        return 0
}

if_down () {
	local IF_NODASH=`echo "$1" | sed -e 's/\-/_/g'`
	local IFTYPE=`echo $1 | sed -e $SED_IFSTR`
	local IFTYPE_NODASH=`echo "$IFTYPE" | sed -e 's/\-/_/g'`

	# Clean up any resolvconf stuff
	if_resolvconf_down $1

	# Do Dee global bridge stuff
	brg_global

	if qt type ${IF_NODASH}_stop ;  then
		# execute user supplied individual interface shutdown
		${IF_NODASH}_stop $1
	elif qt type ${IFTYPE_NODASH}_stop ; then
		# execute user supplied typed interface shutdown
		${IFTYPE_NODASH}_stop $1
	else
		# default action
       		brg_iface $1 down $IPV6_DISABLE
		if_addr_stop $1
	fi

        # Clean up any QoS/fair queuing stuff
        ip_QoSclear $1

	# Clean up IPv6 stuff
	if [ -d ${IPV6_PROC}/conf/${1} ]; then
		for FILE in accept_redirects accept_ra forwarding \
			router_solicitations use_tempaddr; do
			echo  `cat $IPV6_PROC/conf/default/$FILE` \
				> $IPV6_PROC/conf/$1/$FILE
		done
	fi

	# Emit required upstart event - this can be adjusted
	iface_upstart_emit 'net-device-down' "IFACE=${1}" "LOGICAL=${1}" \
				'ADDRFAM=inet' 'METHOD=static'

	true

}       #END if_down

if_lo_up () {

	# Bring up interface lo
	case "$IPV4_DISABLE" in
	YES|Yes|yes)
		;;
	*)
		qt ip addr add 127.0.0.1/8 broadcast 127.255.255.255 dev lo
		;;
	esac

	ip link set lo up \
	&& iface_upstart_emit 'net-device-up' 'IFACE=lo' 'LOGICAL=lo' \
		'ADDRFAM=inet' 'METHOD=static'

}

if_resolvconf_up () {
	if [ $# != 2 -a $# != 3 ]; then
		echo "  Usage: `basename $0`: fn if_resolvconf_up <if-name>  <search-path> <ns1-ip>" 1>&2
		echo "         `basename $0`: fn if_resolvconf_up <if-name> <resolvconf-stdin>" 1>&2
		return 1;
	fi
	
	! qt type resolvconf && return 1

	if [ $# = 3 ]; then
		echo -ne "search ${2}\nnameserver ${3}\n" | resolvconf -a $1
	else
		echo -ne "$2" | resolvconf -a $1
	fi
}

if_resolvconf_down () {
	if [ $# != 1 ]; then
		echo "  Usage: `basename $0`: fn if_resolvconf_down <if-name>" 1>&2
		return 1;
	fi

	! qt type resolvconf && return 1

	# Go and do it...
	resolvconf -d $1
}


