#!/bin/bash

# This file contains supplementary functions for config-ipv4
try_static()
{
	local REALFILE ADDRESSLINE
	if profiled_filename REALFILE "$MYIFACEDIR/ipv4address"; then
		$DENOISE $REALFILE |
		while read ADDRESSLINE; do
			is_yes "$AUTO_BROADCAST" && [ "$ADDRESSLINE" = "${ADDRESSLINE/broadcast/}" ] && \
				ADDRESSLINE="$ADDRESSLINE broadcast +"
			$IP -4 address add dev $NAME $(eval_string $ADDRESSLINE) && print_progress
		done
	fi
	return 0
}

dhcp_cmdline()
{
	local H T
	case `basename $DHCP_CLIENT` in
		dhcpcd)
			if [ -n "$DHCP_HOSTNAME" ]; then
				case "$DHCP_HOSTNAME" in
					AUTO)
						H="-H"
					;;
					localhost)
						[ -n "$HOSTNAME" -a "$HOSTNAME" != "localhost" -a "$HOSTNAME" != "localhost.localdomain" ] && \
						H="-h $HOSTNAME"
					;;
					*)
						H="-h $DHCP_HOSTNAME"
					;;
				esac
			fi
			T=${DHCP_TIMEOUT:+-t $DHCP_TIMEOUT}
			echo "$H -d $T $NAME"
			;;
		dhclient)
			if [ -n "$DHCP_HOSTNAME" ]; then
				case "$DHCP_HOSTNAME" in
					localhost)
						[ -n "$HOSTNAME" -a "$HOSTNAME" != "localhost" -a "$HOSTNAME" != "localhost.localdomain" ] && \
						H="-F $HOSTNAME"
					;;
					*)
						H="-H $DHCP_HOSTNAME"
					;;
				esac
			fi
			T=${DHCP_TIMEOUT:+-T $DHCP_TIMEOUT}
			echo "$H -q $T -pf /var/run/dhclient-$NAME.pid $NAME"
			;;
		*)
			print_error "Can't pick command line for DHCP client '$DHCP_CLIENT'"
			;;
	esac
}

# This function uses check_eth_link(), but DHCP used to work for Ethernet
# mostly (if not only), so functions-eth should be already sourced in such
# case. This may break one day.

try_dhcp()
{
	[ -x "$DHCP_CLIENT" ] || {
		print_error "$DHCP_CLIENT does not exist or is not executable. Try installing dhcpcd/dhclient RPM."
		return 1
	}
	if need_detection; then
		if check_eth_link $NAME; then
			print_progress
		else
			print_nack
			return 1
		fi
	fi
	DHCP_CMDLINE=`dhcp_cmdline`
	$DHCP_CLIENT $DHCP_ARGS $DHCP_CMDLINE >/dev/null
	local RET=$?
	# dhcpcd sets iface down on failure, breaking dhcp-* BOOTPROTOs
	if [ "$RET" != "0" ]; then
		print_nack
		! is_yes $KEEP_DOWN && $IP link set dev $NAME up
	else
		print_progress
	fi
	return $RET
}

try_ipv4ll()
{
	[ -x "$ZCIP_CLIENT" ] || {
		print_error "$ZCIP_CLIENT does not exist or is not executable. Try installing avahi-autoipd RPM."
		return 1
	}
	if need_detection; then
		if check_eth_link $NAME; then
			print_progress
		else
			print_nack
			return 1
		fi
	fi
	$ZCIP_CLIENT --daemonize --wait $NAME
	local RET=$?
	if [ "$RET" != "0" ]; then
		print_nack
	else
		print_progress
	fi
	return $RET
}

process_ipv4rules()
{
	local OP=${1:?missing 1st arg to $FUNCNAME}
	local REVERSE SRCFILE

	if profiled_filename SRCFILE "$MYIFACEDIR/ipv4rule"; then
		[ "$OP" != "del" ] ||
			REVERSE="|tac"

		eval "$DENOISE \"$SRCFILE\" $REVERSE" |
		while read FIRST REST; do
			case "$FIRST" in
				add)
					[ $OP = "del" ] && FIRST=del
				;;
				del)
					# should we restore deleted rules on iface shutdown?
					 [ $OP = "del" ] && FIRST=add
				;;
				*)
					FIRST="$OP $FIRST"
				;;
			esac
			$IP -4 rule $(eval_string $FIRST $REST)
			print_progress
		done
	fi
}

config_ipv4_routes_rules()
{
	# setup routes
	local OP=${1:?missing 1st arg to $FUNCNAME}
	local SRCFILE SUFFIX
	IPV4ADDRESS=($(get_ipv4_addresses $NAME))

	if profiled_filename SRCFILE "$MYIFACEDIR/ipv4route"; then
		[ "$OP" != "del" ] ||
			REVERSE="|tac"

		eval "$DENOISE \"$SRCFILE\" $REVERSE" |
		while read FIRST REST; do
			# If 'dev' is not specified, add current dev.
			SUFFIX=''
			if ! echo "$FIRST $REST" | egrep -q '(^|[[:space:]])(throw|unreachable|prohibit|blackhole)[[:space:]]'; then
				echo "$FIRST $REST" | egrep -q '[[:space:]]dev[[:space:]]' || SUFFIX="dev $NAME"
			fi
			# If operation is not specified, use 'append'.
			case "$FIRST" in
				add|change|append|replace)
					[ $OP = "del" ] && FIRST=del
				;;
				del)
					# should we restore deleted rules on iface shutdown?
					[ $OP = "del" ] && FIRST=add
				;;
				*)
					[ "$OP" = "add" ] && FIRST="append $FIRST" || FIRST="$OP $FIRST"
				;;
			esac
			$IP -4 route $(eval_string $FIRST $REST $SUFFIX)
			print_progress
		done
	fi

	# Setup rules only after routes are Ok, so that route tables are
	# already populated when rule starts routing traffic to them.
	process_ipv4rules $OP
}

get_ipv4_addresses()
{
    local NAME=${1:?missing 1st argument to $FUNCNAME}
    # FIXME should we parse it by more complex regexp?
    printf "$($IP -4 addr show dev $NAME 2>/dev/null|grep -ose "\binet[[:space:]]\+[0-9.]\+"|cut -f2 -d" ")"
}

