# bridge (net-misc/bridge-utils) module for net-scripts
# Version 1.0.0
# Copyright (c) 2004 Gentoo Foundation
# Distributed under the terms of the GNU General Public License V2
# Contributed by Roy Marples (uberlord@gentoo.org)

# Fix any potential localisation problems
# Note that LC_ALL trumps LC_anything_else according to locale(7)
brctl() {
	LC_ALL=C /sbin/brctl "$@"
}

# char* bridge_provides(void)
#
# Returns a string to change module definition for starting up
bridge_provides() {
	echo "bridge"
}

# void bridge_depend(void)
#
# Sets up the dependancies for the module
bridge_depend() {
	after interface tuntap
	before dhcp
	need interface
}

# bool bridge_check_installed(void)
#
# Returns 1 if bridge is installed, otherwise 0
bridge_check_installed() {
	[[ -x /sbin/brctl ]] && return 0
	[[ ${1} == true ]] && eerror "For bridge support, emerge net-misc/bridge-utils"
	return 1
}

# bool bridge_check_depends(void)
#
# Checks to see if we have the needed functions
bridge_check_depends() {
	local f

	for f in interface_down interface_del_addresses interface_set_flag; do
		[[ $(type -t ${f}) == function ]] && continue
		eerror "bridge: missing required function ${f}\n"
		return 1
	done

	return 0
}

# char* bridge_get_vars(char *interface)
#
# Returns a string spaced with possible user set
# configuration variables
bridge_get_vars() {
	echo "bridge_devices_${1}"
}

# char* bridge_get_interfaces(char *interface)
#
# Returns a string spaced with interfaces added to the given bridge
# The awk statement kinda makes sense - would be much easier if the
# brctl program exported the bridge name on each line :/
bridge_get_interfaces() {
	brctl show | awk -v iface=tun0 -v got=0 \
		'$1 == iface || got == 1 { \
			if ( got == 0 ) \
				{ print $4; got=1; } \
			else if ( NF == 1 ) \
				{ print $1; } \
			else \
				{ got = 0; } }' \
		| xargs
}

# bool bridge_stop(char *iface)
#
# Removes the device
# returns 0
bridge_stop() {
	local iface=${1} ifaces=$( bridge_get_interfaces ${1} ) i
	
	bridge_check_installed || return 1
	[[ -z ${ifaces} ]] && return 1

	ebegin "Destroying bridge ${iface}"
	interface_down ${iface}
	
	eindent
	for i in ${ifaces}; do
		veinfo "Removing interface ${i}"
		interface_down ${iface}
		interface_set_flag ${i} promisc false
		brctl delif ${iface} ${i} &>${devnull}
	done
	eoutdent
	
	brctl delbr ${iface} &>${devnull}

	eend 0
	return 0
}

# bool bridge_start(char *iface)
#
# #set up bridge
bridge_start() {
	local iface=${1} ifaces i e
	eval ifaces=\"\$\{bridge_interfaces_${iface}\}\"

	# We don't configure the interface directly
	(( label_counter-- ))

	if [[ -z ${ifaces} ]]; then
		eerror "No bridge interfaces defined for ${iface}"
		return 1
	fi

	# Destroy the bridge if it exists
	bridge_stop ${iface}

	ebegin "Creating Bridge ${iface}"
	e=$( brctl addbr ${iface} 2>&1 )
	if [[ -n ${e} ]]; then
		eend 1 ${e}
		return 1
	fi

	eindent
	for i in ${ifaces}; do
		if ! interface_exists ${i} ; then
			ewarn "interface ${i} does not exist"
			continue
		fi

		vebegin "Adding interface ${i}"
		e=$( brctl addif ${iface} ${i} 2>&1 \
			&& interface_del_addresses ${i} \
			&& interface_set_flag ${i} promisc true )
		if [[ -n ${e} ]]; then
			eend 1 ${e}
			return 1
		fi
	done
	eoutdent

	eend 0
	return 0
}
