#!/bin/bash 

# Copyright (C) 2015-2016 NIWA Hideyuki

FULCONDIR=/var/lib/fulcon

FULCONDRIVER=`fulcon driver-name`
PATH=/usr/lib/fulcon/driver/$FULCONDRIVER:/usr/lib/fulcon/lib:$PATH

umask 022

# function usage
usage()
{
	echo "usage: net-add CONTAINER_NAME IPADDR/MASK NIC_NUMBER [ MAC1 MAC2 ]"
}

NETARGS=$@

# check options
FLG_D=0 ; NETDEV=""
FLG_G=0 ; LXCGATEWAY=""
FLG_B=0 ; LXCBR="0"

#while getopts d:g:b: OPT ; do
#  case $OPT in
#  d) FLG_D=1 ; NETDEV=$OPTARG ;;
#  g) FLG_G=1 ; LXCGATEWAY=$OPTARG ;;
#  b) FLG_B=1 ; LXCBR=$OPTARG ;;
#  \? ) usage; exit -1;;
#  esac
#done
#shift $((OPTIND - 1))

# check args
if [ $# -ne 3 -a $# -ne 5 ]; then
	usage
	exit -1
fi

# get mac address
if [ $# -eq 5 ]; then
	MACFLG=1
	MAC1=$4
	MAC2=$5
else
	MACFLG=0
	MAC1=""
	MAC2=""
fi

LXCNAME=$1
LXCBRIP=`net-ipv4 -g $2`
if [ $? -ne 0 ]; then
	echo "error: specified parameter of $LXCNAME have to be IP_address/Mask format"
	exit -1
fi
NUM=$3

# check ip address of bridge
if [ x"`ip a show $NETDEV | egrep "inet " | awk '{print $2}'`" == x"" ]; then
	echo "error: $NETDEV has not an IP address"
	exit -1
fi

# check unnecessary bridges
for i in `brctl show | egrep fulcon | awk '(NF==3){print $1}'`
do
	ip link set $i down
	brctl delbr $i
done

RBR=0
BRNO=0
BNO=0
for i in `brctl show | egrep fulcon | awk '{print $1}'`
do
	BIP=`ip a show $i | awk '$1=="inet"{print $2}'`
	BIP=`net-ipv4 -g $BIP`
	BNO=`echo $i | sed -e "s/fulcon//"`
	if [ x"$BIP" == x"$LXCBRIP" ]; then
		RBR=1
		break
	fi
	if [ $BNO -gt $BRNO ]; then
		BRNO=$BNO
	fi
done
if [ $RBR -eq 0 ]; then
	LXCBR=`expr $BRNO + 1`
else
	LXCBR=$BNO
fi

# check a BRIDGE_NUMBER
expr "$LXCBR" + 1 >& /dev/null
if [ $? -gt 1 ]; then
	echo "error: BRIDGE_NUMBER is not a integer"
	exit -1
fi
LXCBR="fulcon"$LXCBR

LXCIP=`echo $2 | awk -F / '{printf "%s",$1}'`
LXCMASK=`echo $2 | awk -F / '{printf "%s",$2}'`


if [ x$LXCGATEWAY == x"" ]; then
	LXCGATEWAY=$LXCBRIP
fi

if [ x$NETDEV != x"" ]; then
	ip a show $NETDEV >& /dev/null
	if [ $? -ne 0 ]; then
		echo "error: device $NETDEV does not exist."
		exit -1
	fi
	LXCBRIP=`ip a show $NETDEV | awk 'NR==3{print $2}' | awk -F / '{print $1}'`
	DEVMASK=`ip a show $NETDEV | awk 'NR==3{print $2}' | awk -F / '{print $2}'`
	if [ x"$LXCBRIP" == x"" ]; then
		LXCBRIP=`ip a show $LXCBR | awk 'NR==3{print $2}' | awk -F / '{print $1}'`
		DEVMASK=`ip a show $LXCBR | awk 'NR==3{print $2}' | awk -F / '{print $2}'`
	fi
fi

setup_network()
{
	mkdir -p /var/run/netns/
	ln -s /proc/${LXCPROC}/ns/net /var/run/netns/${LXCNAME}_${NUM}

	ip link add name ${LXCNAME}_${NUM} type veth peer name vg${LXCNAME}_${NUM} >& /dev/null

	# set/get MAC1
	if [ x"$MAC1" != x"" ]; then
		ip link set ${LXCNAME}_${NUM} address $MAC1 
	else
		MAC1=`ip addr show ${LXCNAME}_${NUM} | egrep link/ether | awk '{print $2}'`
#		MAC1=`echo $MAC1 | awk -F : '{printf "52:54:00:%2s:%2s:%2s",$4,$5,$6}'`
	fi

	ip link set ${LXCNAME}_${NUM} up

	brctl show $LXCBR |& egrep 'No such device' >& /dev/null
	if [ $? -eq 0 ]; then
		brctl addbr $LXCBR
		ip link set $LXCBR up
		BR_BRCAST=`net-ipv4 -b ${LXCBRIP}/${LXCMASK}`
		ip addr add ${LXCBRIP}/${LXCMASK} broadcast $BR_BRCAST dev $LXCBR
		ip link set $LXCBR promisc on
	fi
	brctl addif $LXCBR ${LXCNAME}_${NUM} >& /dev/null

	# setting up of IP address
	LXCFBROADCAST=`net-ipv4 -b "${LXCIP}/${LXCMASK}"`
	ip link set vg${LXCNAME}_${NUM} netns ${LXCNAME}_${NUM} >& /dev/null

	# get/set MAC2
	if [ x"$MAC2" != x"" ]; then
		ip netns exec "${LXCNAME}_${NUM}" ip link set vg${LXCNAME}_${NUM} address $MAC2
	else
		MAC2=`ip netns exec "${LXCNAME}_${NUM}" ip addr show vg${LXCNAME}_${NUM} | egrep link/ether | awk '{print $2}'`
#		MAC2=`echo $MAC2 | awk -F : '{printf "52:54:00:%2s:%2s:%2s",$4,$5,$6}'`
	fi

	# Setting of network in container
	ip netns exec ${LXCNAME}_${NUM} ip link set vg${LXCNAME}_${NUM} up
	IPFLG=""
	while [ x${IPFLG} == x"inet6" -o x${IPFLG} != x"inet" ]; 
	do
		IPFLG=`ip netns exec "${LXCNAME}_${NUM}" ip addr show vg${LXCNAME}_${NUM} | awk 'NR==3{print $1}'`
		ip netns exec "${LXCNAME}_${NUM}" ip addr add ${LXCIP}/${LXCMASK} dev vg${LXCNAME}_${NUM} broadcast $LXCFBROADCAST >& /dev/null
		OLDIPADR=`ip netns exec "${LXCNAME}_${NUM}" ip addr show vg${LXCNAME}_${NUM} | awk 'NR==3{print $2}'`
		sleep 1
	done
	while [ x${OLDIPADR} != x${LXCIP}/${LXCMASK} ]; 
	do 
		OLDIPADR=`ip netns exec "${LXCNAME}_${NUM}" ip addr show vg${LXCNAME}_${NUM} | awk 'NR==3{print $2}'`
		if [ x${OLDIPADR} != x${LXCIP}/${LXCMASK} ]; then
			ip netns exec ${LXCNAME}_${NUM} ip addr del ${OLDIPADR} dev vg${LXCNAME}_${NUM}
			ip netns exec ${LXCNAME}_${NUM} ip addr add ${LXCIP}/${LXCMASK} dev vg${LXCNAME}_${NUM} broadcast $LXCFBROADCAST >& /dev/null
		fi
		sleep 1
	done

	# setting up of gateway
	if [ x$LXCGATEWAY != x"" ]; then
		ip netns exec ${LXCNAME}_${NUM} ip route delete default >& /dev/null
		IPADDR=$LXCGATEWAY
		IPMASK=$LXCMASK
		ip netns exec ${LXCNAME}_${NUM} ip route add default via ${IPADDR}
	fi

	rm -f /var/run/netns/${LXCNAME}_${NUM}

	if [ x$NETDEV != x"" ]; then
		# setting of promiscuous mode
		ip addr del $LXCBRIP dev $NETDEV >& /dev/null
		ip addr add 0.0.0.0 dev $NETDEV >& /dev/null
		ip link set $NETDEV promisc on

		brctl show $LXCBR | egrep -w $NETDEV >& /dev/null
		if [ $? -ne 0 ]; then
			brctl addif $LXCBR $NETDEV 
		fi
	fi

	echo "${LXCNAME}_${NUM} ${LXCIP}/${IPMASK}"
}

LXCPROC=`fulcon-find-proc ${LXCNAME}`
if [ $? -eq 0 ]; then
	setup_network
fi

# setup container address
NETARGS="`echo $NETARGS | cut -d ' ' -f 2-`"
mkdir -p $FULCONDIR/container/$LXCNAME/net
rm -f $FULCONDIR/container/$LXCNAME/net/${LXCNAME}_${NUM}
if [ $MACFLG -eq 1 ]; then
	echo 'net-add $1' "$NETARGS" > $FULCONDIR/container/$LXCNAME/net/${LXCNAME}_${NUM}
else
	echo 'net-add $1' "$NETARGS $MAC1 $MAC2" > $FULCONDIR/container/$LXCNAME/net/${LXCNAME}_${NUM}
fi

exit 0
