ipw 7.67 KB
#!/bin/bash

#    Copyright (C) 2013 Artyom A Anikeev <anikeev@ut.mephi.ru> 0xB5385841,
#    Dmitry Yu Okunev <xai@mephi.ru> 0x8E30679C
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.

eerror() {
	echo "$@" >&2
}

newconfig_open() {
	echo -n > "$NEWCONFIG_TMPPATH"
}

newconfig_write() {
	LINE="$1"; shift;

	[[ "$NEWCONFIG" -eq 0 ]] && return

	echo "$LINE" >> "$NEWCONFIG_TMPPATH"
}

newconfig_commit() {
	rm -f "$CONFIG_PATH"
	mv "$NEWCONFIG_TMPPATH" "$CONFIG_PATH"
}

newconfig_push() {
	BUFNUM="$1";	shift;
	LINE="$1";	shift;

	BUF[$BUFNUM]="${BUF[$BUFNUM]}
$LINE"
}

newconfig_pushpopall() {
	BUFNUMTO="$1";		shift;
	BUFNUMFROM="$1";	shift;

	newconfig_push "$BUFNUMTO" "${BUF[$BUFNUMFROM]}"
	newconfig_popall "$BUFNUMFROM"
}

newconfig_popall() {
	BUFNUM="$1";	shift;

	BUF[$BUFNUM]=""
}

newconfig_popallwrite() {
	BUFNUM="$1";	shift;

	newconfig_write "${BUF[$BUFNUM]}"
	BUF[$BUFNUM]=""
}

parse_vlan_subvlan_bridge() {
	VLAN_N_BRIDGE="$1"; shift

	if [[ "${VLAN_N_BRIDGE:0:1}" = ":" ]]; then 
		VLAN=""
		BRNAME="${VLAN_N_BRIDGE:1}"
	else
		# Splitting by ":"
		WORDS=( ${VLAN_N_BRIDGE//[:]/ } )

		# The second word defines interface name. If it's empty, "vlan$VLAN.$SUBVLAN" is used.
		VLANNAME="${WORDS[0]}"
		BRNAME="${WORDS[1]}"

		# Splitting by "."
		WORDS=( ${VLANNAME//[.]/ } )

		# The second word defines subvlan (1q-in-1q) if it's used. It's empty if no subvlan is used.
		VLAN="${WORDS[0]}"
		SUBVLAN="${WORDS[1]}"
	fi

	# Checking if no "vlan(.subvlan)?" is set
	if ! [[ "${VLAN_N_BRIDGE: -1}" = ":" ]]; then
		# Setting default values
		[[ "$SUBVLAN" = "" ]] && BRNAME="${BRNAME:-vlan${VLAN}}" || BRNAME="${BRNAME:-vlan${VLAN}.${SUBVLAN}}"
	fi

	return;
}

CONFIG_PATH="./ipw-configsample"

source "$CONFIG_PATH"

NEWCONFIG_TMPPATH="/tmp/.~ipw"


CMD="$1"; shift;

NEWCONFIG=0
case "$CMD" in
	add1qif) #allow to add slave interface in bonding
		NEWCONFIG=1	# we need to update the config after the command

		NEW_D1Q_IFACE="$1"; shift
		NEW_SLAVE="$1"; shift

		# checking for duplicated slaves or d1q_ifaces
		D1Q_IFACE_USED=0
		for D1Q_IFACE in ${D1Q_IFACES[@]}; do
			if [[ "$D1Q_IFACE" = "$NEW_D1Q_IFACE" ]]; then
				D1Q_IFACE_USED=1
			fi
			SLAVES_VARIABLE="${D1Q_IFACE}_SLAVES"
			SLAVES_VARIABLE="${SLAVES_VARIABLE//[.]/_}[@]"
			for SLAVE in "${!SLAVES_VARIABLE}"; do
				if [[ "$SLAVE" = "$NEW_SLAVE" ]]; then
					eerror "This interface have already been enslaved"
					exit -1
				fi
			done
		done

		if [[ $D1Q_IFACE_USED -eq 0 ]]; then
			D1Q_IFACES[ ${#D1Q_IFACES} ]="$NEW_D1Q_IFACE"
		fi

		SLAVES_VARIABLE="${NEW_D1Q_IFACE}_SLAVES"
		SLAVES_VARIABLE="${SLAVES_VARIABLE//[.]/_}"
		eval "${SLAVES_VARIABLE}[\${#${SLAVES_VARIABLE}}]=\"$NEW_SLAVE\""

		;;
	addbrif) #allow to add bridge/vlan in bonding
		NEWCONFIG=1	# we need to update the config after the command

		NEW_D1Q_IFACE="$1"; shift
		NEW_VLAN_SUBVLAN="$1"; shift
		NEW_BRIDGE="$1"; shift

		[[ -z $NEW_BRIDGE ]] && NEW_VLAN_N_BRIDGE="${NEW_VLAN_SUBVLAN}" || NEW_VLAN_N_BRIDGE="${NEW_VLAN_SUBVLAN}:${NEW_BRIDGE}"

		D1Q_IFACE_USED=0

		for D1Q_IFACE in ${D1Q_IFACES[@]}; do
			if [[ "$D1Q_IFACE" = "$NEW_D1Q_IFACE" ]]; then
				D1Q_IFACE_USED=1
				break;
			fi
		done

		parse_vlan_subvlan_bridge "${NEW_VLAN_N_BRIDGE}"
		NEW_VLAN=$VLAN
		NEW_SUBVLAN=$SUBVLAN

		if [[ $D1Q_IFACE_USED -eq 0 ]]; then
			eerror "There's no such interface: $NEW_D1Q_IFACE"
			exit -1
		fi

		VLAN_N_BRIDGE_VARIABLE="${NEW_D1Q_IFACE}_VLAN_N_BRIDGES"
		VLAN_N_BRIDGE_VARIABLE="${VLAN_N_BRIDGE_VARIABLE//[.]/_}[@]"
		for VLAN_N_BRIDGE in "${!VLAN_N_BRIDGE_VARIABLE}"; do
			parse_vlan_subvlan_bridge "${VLAN_N_BRIDGE}"
 			if [[ "$VLAN" = "$NEW_VLAN" && "$SUBVLAN" = "$NEW_SUBVLAN" ]]; then
				eerror "This vlan is alredy used"
				exit -1
			fi		
		done

		VLAN_N_BRIDGE_VARIABLE="${NEW_D1Q_IFACE}_VLAN_N_BRIDGES"
		VLAN_N_BRIDGE_VARIABLE="${VLAN_N_BRIDGE_VARIABLE//[.]/_}"
		eval "${VLAN_N_BRIDGE_VARIABLE}[\${#${VLAN_N_BRIDGE_VARIABLE}}]=\"$NEW_VLAN_N_BRIDGE\""

			
		#D1Q_IFACES[ ${#D1Q_IFACES}]
		
		;;
	addbr) #allow to add bridge without interfaces
		NEWCONFIG=1	# we need to update the config after the command

		NEW_D1Q_IFACE="$1"; shift
		NEW_BRIDGE="$1"; shift

		VLAN_N_BRIDGE_VARIABLE="${NEW_D1Q_IFACE}_VLAN_N_BRIDGES"
		VLAN_N_BRIDGE_VARIABLE="${VLAN_N_BRIDGE_VARIABLE//[.]/_}"
		eval "${VLAN_N_BRIDGE_VARIABLE}[\${#${VLAN_N_BRIDGE_VARIABLE}}]=\":${NEW_BRIDGE}\""

		;;
	addipcmd) #allow to add ip commnds for bridges/vlans
		NEWCONFIG=1	# we need to update the config after the command
		NEW_BRIDGE="$1"; shift

		NEW_IP_CMD="$@"

		if [[ "${NEW_BRIDGE}" != "" ]]; then

			# Getting commands for "ip"
			IP_CMDS_VARIABLE="${NEW_BRIDGE//[.]/_}_IP" # br is used to start variable's name from non numerical symbol
			IP_CMDS_VARIABLE="${IP_CMDS_VARIABLE}"
			eval "${IP_CMDS_VARIABLE}[\${#${IP_CMDS_VARIABLE}}]=\"$NEW_IP_CMD\""
			#echo $IP_CMDS_VARIABLE

		fi


		#ADDRMASK="$1"; shift
		#GW="$1";  shift

		# TODO: implement this
		#bond0_SLAVES[ ${#bond0_SLAVES
		#[@]} ]="eth2"
		;;
	fix)
		#brctl addif bond0 eth2
		;;
	*)
		;;
esac

newconfig_open
newconfig_write "#"
newconfig_write ""
newconfig_write "D1Q_IFACES=("

for D1Q_IFACE in ${D1Q_IFACES[@]}; do
	newconfig_write	"	$D1Q_IFACE"

	newconfig_push 128 "${D1Q_IFACE}_SLAVES=("

	haveaslave=0
	SLAVES_VARIABLE="${D1Q_IFACE}_SLAVES"
	SLAVES_VARIABLE="${SLAVES_VARIABLE//[.]/_}[@]"
	for SLAVE in "${!SLAVES_VARIABLE}"; do
		newconfig_push 128 "	$SLAVE";
		haveaslave=1
	done

	newconfig_push 128 ")"

	# If there're no slaves then don't write anything about them
	[[ $haveaslave -ne 0 ]] && newconfig_pushpopall 1 128 || newconfig_popall 128

	VLAN_N_BRIDGE_VARIABLE="${D1Q_IFACE}_VLAN_N_BRIDGES"
	VLAN_N_BRIDGE_VARIABLE="${VLAN_N_BRIDGE_VARIABLE//[.]/_}[@]"
	
	newconfig_push 1 "${D1Q_IFACE}_VLAN_N_BRIGES=("
	
	for VLAN_N_BRIDGE in "${!VLAN_N_BRIDGE_VARIABLE}"; do
		newconfig_push 1 "	${VLAN_N_BRIDGE}"

		parse_vlan_subvlan_bridge "${VLAN_N_BRIDGE}"

		# Checking if no "vlan(.subvlan)?" is set
		if [[ "${BRNAME}" != "" ]]; then
			#echo $BRNAME
			# Getting commands for "ip"
			IP_CMDS_VARIABLE="${BRNAME//[.]/_}_IP"
			newconfig_push 128 "${IP_CMDS_VARIABLE}=("
			IP_CMDS_VARIABLE="${IP_CMDS_VARIABLE}[@]"
			hasanIP_CMD=0
			for IP_CMD in "${!IP_CMDS_VARIABLE}"; do
				newconfig_push 128 "	\"$IP_CMD\""
				echo ip $IP_CMD dev $BRNAME
				hasanIP_CMD=1
			done

			newconfig_push 128 ")"
			newconfig_push 128 ""

			[[ $hasanIP_CMD -ne 0 ]] && newconfig_pushpopall 2 128 || newconfig_popall 128
		else

			# Getting commands for "ip"
			#echo OK
			IP_CMDS_VARIABLE="vlan${VLANNAME//[.]/_}_IP"
			newconfig_push 128 "${IP_CMDS_VARIABLE}=("
			IP_CMDS_VARIABLE="${IP_CMDS_VARIABLE}[@]"
			hasanIP_CMD=0
			for IP_CMD in "${!IP_CMDS_VARIABLE}"; do
				newconfig_push 128 "	\"$IP_CMD\""
				echo ip $IP_CMD dev $VLANNAME
				hasanIP_CMD=1
			done

			newconfig_push 128 ")"
			newconfig_push 128 ""

			[[ $hasanIP_CMD -ne 0 ]] && newconfig_pushpopall 2 128 || newconfig_popall 128
			
		fi

		printf "br: %-10s vlan:%4s subvlan:%4s\n" "$BRNAME" "$VLAN" "$SUBVLAN"
	done
	newconfig_push 1 ")"
	

done

newconfig_write ")"

newconfig_popallwrite 1
newconfig_popallwrite 2
newconfig_popallwrite 3

echo ${D1Q_IFACES[@]}

#[[ $NEWCONFIG -ne 0 ]] && newconfig_commit

exit 0