# Copyright 2007-2008 Roy Marples <roy@marples.name>
# All rights reserved. Released under the 2-clause BSD license.

ifconfig_depend()
{
	program /sbin/ifconfig
	provide interface
}

_exists()
{
	# Only FreeBSD sees to have /dev/net .... is there something
	# other than ifconfig we can use for the others?
	if [ -d /dev/net ]; then
		[ -e /dev/net/"${IFACE}" ]
	else
		ifconfig "${IFACE}" >/dev/null 2>&1
	fi
}

_up()
{
	ifconfig "${IFACE}" up
}

_down()
{
	ifconfig "${IFACE}" down
}

_ifindex()
{
	local x= i=1
	case "${RC_UNAME}" in
		FreeBSD|DragonFly)
			for x in /dev/net[0-9]*; do
				if [ "${x}" -ef /dev/net/"${IFACE}" ]; then
					echo "${x#/dev/net}"
					return 0
				fi
				i=$((${i} + 1))
			done
			;;
		default)
			for x in $(ifconfig -l); do
				if [ "${x}" = "${IFACE}" ]; then
					echo "${i}"
					return 0
				fi
				i=$((${i} + 1))
			done
			;;
	esac

	# Return the next available index
	echo "${i}"
	return 1
}

_ifconfig_ent()
{
	LC_ALL=C ifconfig "${IFACE}" 2>/dev/null | while read ent rest; do
   		case "${ent}" in
			$1) echo "${rest}";;
		esac
	done
}

_get_mac_address()
{
	local ent="ether"
	case "${RC_UNAME}" in
		NetBSD|OpenBSD) ent="address:";;
	esac

	case $(_ifconfig_ent "${ent}") in
		00:00:00:00:00:00);;
		44:44:44:44:44:44);;
		FF:FF:FF:FF:FF:FF);;
		"") return 1;;
		*) echo "${address}";;
	esac

	return 0;
}


_is_wireless()
{
	case "$(_ifconfig_ent "media:")" in
		IEEE802.11*|"IEEE 802.11 Wireless"*) return 0;;
		*) return 1;;
	esac
}

_get_inet_address()
{
	local inet= address= n= netmask= rest=
	LC_ALL=C ifconfig "${IFACE}" | while read inet address n netmask rest; do
		if [ "${inet}" = "inet" ]; then
			echo "${address}/$(_netmask2cidr "${netmask}")"
			return 0
		fi
	done
}

_add_address()
{
	local inet6=

	case "$@" in
		*:*) inet6=inet6;;
	esac

	if [ "${metric:-0}" != "0" ]; then
		set -- "$@" metric ${metric}
	fi

	# ifconfig doesn't like CIDR addresses
	case "${RC_UNAME}" in
		OpenBSD)
			local ip="${1%%/*}" cidr="${1##*/}" netmask=
			if [ -n "${cidr}" -a "${cidr}" != "${ip}" ]; then
				netmask="$(_cidr2netmask "${cidr}")"
				shift
				set -- "${ip}" netmask "${netmask}" "$@"
			fi
			;;
	esac

	ifconfig "${IFACE}" ${inet6} "$@" alias
}

_add_route()
{
	if [ $# -gt 3 ]; then
		if [ "$3" = "gw" -o "$3" = "via" ]; then
			local one=$1 two=$2
			shift; shift; shift
			set -- "${one}" "${two}" "$@"
		fi
	fi

	case "$@" in
		*:*) route add -inet6 "$@";;
		*)   route add        "$@";;
	esac
}

_delete_addresses()
{
	einfo "Removing addresses"
	eindent
	LC_ALL=C ifconfig "${IFACE}" | while read inet address ali rest; do
		case "${inet}" in
			inet|inet6)
				if [ "${address}" = "alias" ]; then
					address="${ali}"
				fi
				case "${address}" in
					*"%${IFACE}"|::1) continue;;
					127.0.0.1) [ "${IFACE}" = "lo0" ] && continue;;
				esac
				einfo "${address}"
				ifconfig "${IFACE}" "${inet}" "${address}" -alias
				eend $?
				;;
		esac
	done
	eoutdent
	return 0
}

_show_address()
{
	einfo "received address $(_get_inet_address "${IFACE}")"
}

_has_carrier()
{
	case "$(_ifconfig_ent "status:")" in
		""|active|associated) return 0;;
		*) return 1;;
	esac
}

ifconfig_pre_start()
{
	local config="$(_get_array "ifconfig_${IFVAR}")" conf= arg= args=
	local IFS="$__IFS"

	[ -z "${config}" ] && return 0

	veinfo "Running ifconfig commands"
	eindent
	for conf in ${config}; do
		unset IFS
		args=
		for arg in ${conf}; do
			case ${arg} in
				[Dd][Hh][Cc][Pp]);;
				[Nn][Oo][Aa][Uu][Tt][Oo]);;
				[Nn][Oo][Ss][Yy][Nn][Cc][Dd][Hh][Cc][Pp]);;
				[Ss][Yy][Nn][Cc][Dd][Hh][Cc][Pp]);;
				[Ww][Pp][Aa]);;
				*) args="${args} ${arg}";;
			esac
		done

		[ -z "${args}" ] && continue
		vebegin "ifconfig${args}"
		eval ifconfig "${IFACE}" "${args}"
		veend $?
	done
	eoutdent

	return 0
}

_ifconfig_ipv6_tentative()
{
	local inet= address= rest=
	LC_ALL=C ifconfig "${IFACE}" | while read inet address rest; do
	 	case "${inet}" in
			inet6)
				case "${rest}" in
					*" "tentative*) return 2;;
				esac
				;;
		esac
	done
	[ $? = 2 ]
}

ifconfig_post_start()
{
	if _ifconfig_ipv6_tentative; then
		ebegin "Waiting for IPv6 addresses"
		while true; do
			_ifconfig_ipv6_tentative || break
		done
		eend 0
	fi
}