#!/bin/bash

BRIDGE_NAME="vstorage-iscsi"
BRCTL="/usr/sbin/brctl"
ARPING="/sbin/arping"
TGTD_PORT=3260
IP_CMD="/sbin/ip"

function iscsi_get_netdev()
{
# Get a list of interfaces, excluding ones with LOOPBACK NOARP or SLAVE flags
# Accept mask: eth*[0-9]|tr*[0-9]|wlan[0-9]|ath[0-9]|ip6tnl*[0-9]|mip6mnha*[0-9]|bond[0-9]
	NETDEVICES=`${IP_CMD} a l | awk '
/^[[:digit:]]+:/ && /\<UP\>/ && !/\<LOOPBACK\>/ && !/\<SLAVE\>/ && !/\<NOARP\>/{
	if ($2 ~ /^en.*|^eth.*[0-9]+|^virbr[0-9]+|^em.*[0-9]+|^p[0-9]+p[0-9]+|^tr.*[0-9]+|^wlan[0-9]+|^ath[0-9]+|^ip6tnl.*[0-9]+|^mip6mnha.*[0-9]+|^vlan.*|^bond.*[0-9]+|^ib[0-9]+/) print $2;
}' | sed -e 's/:$//' -e 's/@.*//'`

	local tmp_list=""
	# Open vSwitch mode - IP assigned to bridge over device
	if [ -d "/sys/module/openvswitch" ]; then
		for dev in $NETDEVICES; do
			local tmp=`$OVSCTL_CMD iface-to-br $dev 2>/dev/null`
			[ $? -ne 0 ] && tmp="$dev"
			tmp_list="$tmp_list $tmp"
		done
	NETDEVICES="$tmp_list"
	fi

	# step 2 - filter out devices without IP address
	tmp_list=""
	for dev in $NETDEVICES; do
		local tmp=`${IP_CMD} a l $dev | awk -v dev=$dev \
			'/^^[\ \t]+inet6? / { print(dev); exit; }'`
		[ -n "$tmp" ] && tmp_list="$tmp_list $tmp"
	done
	echo "$tmp_list"
}

function iscsi_update_arp() {
	local addr="$1"
	if [ ! -x $ARPING ]; then
		echo "Can't find executable $ARPING" 1>&2
		return 1
	fi

	net_dev=`iscsi_get_netdev 2>/dev/null`
	if [ -z "$net_dev" ]; then
		echo "No active network interfaces" 1>&2
		return 2
	fi

	for d in $net_dev; do
		$ARPING -c 1 -w 1 -q -D -A -I $d $addr
	done

	return 0
}

function iscsi_remove_addr() {
	while [ "${#}" -gt 0 ]; do
		local addr="$1"; shift
		local addr_exist=`/sbin/ip addr show $BRIDGE_NAME 2>/dev/null | grep "$addr"`
		[ -n "$addr_exist" ] && /sbin/ip addr del "$addr" dev "$BRIDGE_NAME" >/dev/null 2>&1
	done
}

function iscsi_add_addr() {
	local addr="$1"
	local bridge_exist=`$BRCTL show | grep "$BRIDGE_NAME"`
	if [ -z "$bridge_exist" ] ; then
		echo "Bridge $BRIDGE_NAME doesn't exist on this host" 1>&2
		return 1
	fi
	addr_exist=`/sbin/ip addr show $BRIDGE_NAME 2>/dev/null | grep "$addr"`
	if [ -n "$addr_exist" ] ; then 
		echo "Address $addr already exist on bridge $BRIDGE_NAME" 1>&2
	else
		/sbin/ip addr add "$addr" dev "$BRIDGE_NAME"
		if [ $? -ne 0 ] ; then
			echo "Failed to add address $addr to bridge $BRIDGE_NAME" 1>&2
			return 2
		fi
	fi
	iscsi_update_arp `echo $addr | cut -d '/' -f 1`
	[ $? -ne 0 ] && return 3
	return 0
}

function iscsi_validate_addr() {
	tmp_addr="$1"
	out=""
	for addr in $tmp_addr; do
		# validate addresses
		addr=`echo $addr | cut -d '/' -f 1`
		/bin/ipcalc -c $addr
		if [ $? -ne 0 ] ; then
			echo "Address '$addr' is wrong." 1>&2
			return
		fi
		/bin/ipcalc -c -6 $addr >/dev/null 2>&1
		if [ $? -ne 0 ] ; then
			/bin/ipcalc -c -4 $addr >/dev/null 2>&1
			if [ $? -ne 0 ] ; then
				echo "Address '$addr' is wrong." 1>&2
				return
			fi
			out="$addr/32 $out"
		else
			out="$addr/64 $out"
		fi
	done
	echo "$out"
}

function iscsi_init_host() {
	# make bridge
	bridge_exist=`$BRCTL show | grep $BRIDGE_NAME`
	if [ -z "$bridge_exist" ] ; then
		$BRCTL addbr $BRIDGE_NAME
		if [ $? -ne 0 ] ; then
			echo "Unable create bridge $BRIDGE_NAME" 1>&2
			return 1
		fi
	fi

	return 0
}
