#!/bin/sh

. /etc/rc.subr
. /etc/network.subr

load_rc_config netif

# Configure IPv6 on the lagg using the synthetic interface's rc.conf values.
# Keep the variable remapping local to this subshell.
ipv6_lagg_up()
(
	local var value suffix ifconfig_args

	afexists inet6 || return 0
	if ! ipv6if $hn && ! checkyesno ipv6_activate_all_interfaces
	then
		return 0
	fi

	for var in `list_vars "ifconfig_${hn}_*"`
	do
		suffix=${var#ifconfig_${hn}_}
		case $suffix in
		ipv6|alias*)
			eval value=\"\$$var\"
			setvar "ifconfig_${lagg}_${suffix}" "$value"
			;;
		esac
	done
	value=`get_if_var $hn ipv6_prefix_IF`
	setvar "ipv6_prefix_${lagg}" "$value"
	for var in `list_vars "ipv6_ifconfig_${hn}"` \
	    `list_vars "ipv6_ifconfig_${hn}_alias*"`
	do
		suffix=${var#ipv6_ifconfig_${hn}}
		eval value=\"\$$var\"
		setvar "ipv6_ifconfig_${lagg}${suffix}" "$value"
	done
	ipv6_network_interfaces="$ipv6_network_interfaces $lagg"

	ifconfig $lagg inet6 -ifdisabled up || return 1
	for ifconfig_args in "`ifconfig_getargs $lagg ipv6`" \
	    "`get_if_var $lagg ipv6_ifconfig_IF`"
	do
		[ -n "$ifconfig_args" ] || continue
		# Accept legacy values without the address-family keyword.
		case $ifconfig_args in
		inet6|inet6[[:space:]]*) ;;
		*) ifconfig_args="inet6 $ifconfig_args" ;;
		esac
		ifconfig $lagg $ifconfig_args || return 1
	done
	ipv6_up $lagg
	ipv6_accept_rtadv_up $lagg
	return 0
)

#
# Customized per-interface setup, e.g. hyperv_vfup.hn1
#
# NOTE-CUSTOMIZE:
# Comment this out, if this script is used as template
# for the customized per-interface setup.
#
if [ -f /usr/libexec/hyperv/hyperv_vfup.$1 ]
then
	/usr/libexec/hyperv/hyperv_vfup.$1
	exit $?
fi

# NOTE-CUSTOMIZE:
#hn=${0##*.}
hn=$1
hn_unit=`echo $hn | sed 's/[^0-9]*//g'`

vf=`sysctl -n dev.hn.$hn_unit.vf`
if [ ! $vf ]
then
	# Race happened; VF was removed, before we ran.
	echo "$hn: VF was detached"
	exit 0
fi

#
# Create laggX for hnX.
# Add VF and hnX to laggX.
#

lagg=lagg$hn_unit

ifconfig $lagg > /dev/null 2>&1
if [ $? -ne 0 ]
then
	#
	# No laggX, create it now.
	#
	ifconfig $lagg create > /dev/null 2>&1
	if [ $? -ne 0 ]
	then
		echo "$lagg creation failed"
		exit 1
	fi

	#
	# Stop accepting advertisements on hnX.  Leave IPv6 enabled and its
	# link-local address in place until lagg has purged the member's
	# IPv6 addresses, prefixes, and default routers.
	#
	if afexists inet6
	then
		ifconfig $hn inet6 -accept_rtadv || exit 1
	fi

	# Configure laggX (failover), add hnX and VF to it.
	ifconfig $lagg laggproto failover laggport $hn laggport $vf || exit 1
	if afexists inet6
	then
		# lagg does not purge an IPv6-disabled member or one without a
		# link-local address.  Disable IPv6 and remove any addresses left.
		# SLAAC addresses are relearned on lagg, not copied as permanent.
		ifconfig $hn inet6 ifdisabled || exit 1
		inet6_status=`ifconfig $hn inet6` || exit 1
		for addr in `printf '%s\n' "$inet6_status" | \
		    awk '$1 == "inet6" { print $2 }'`
		do
			ifconfig $hn inet6 "$addr" -alias || exit 1
		done
		ifconfig $lagg inet6 no_dad
	fi

	#
	# Stop dhclient on hnX, if any.
	#
	pidfile=/var/run/dhclient.$hn.pid
	if [ -f $pidfile ]
	then
		kill -TERM `cat $pidfile`
	fi

	#
	# Remove all configured IPv4 addresses on hnX, e.g.
	# configured by dhclient.  laggX will take over the
	# network operations.
	#
	# Enumerate addresses; an empty ifconfig -alias may return success.
	ipv4_down $hn

	#
	# Use hnX's configuration for laggX
	#
	# NOTE-CUSTOMIZE:
	# If this script is used as template for the customized
	# per-interface setup, replace this with whatever you
	# want to do with the laggX.
	#
	if dhcpif $hn;
	then
		ifconfig $lagg up
		if syncdhcpif $hn;
		then
			dhclient $lagg
		else
			dhclient -b $lagg
		fi
	else
		ifconfig_args=`ifconfig_getargs $hn`
		if [ -n "$ifconfig_args" ]
		then
			ifconfig $lagg $ifconfig_args
		fi
	fi
	ipv6_lagg_up || exit 1
else
	#
	# laggX exists.  Check whether VF was there or not.
	# If VF was not added to laggX, add it now.
	#
	ifconfig $lagg | grep "laggport: $vf" > /dev/null 2>&1
	if [ $? -ne 0 ]
	then
		ifconfig $lagg laggport $vf
	fi
fi
