#!/bin/bash
#
# VERSION=16
# CHANGES="add broadcast default route for lan-wan mode"

### contstants ###
export PATH=$PATH:/sbin/:/bin:/usr/sbin:/usr/bin

### functions ###
function log () {
	echo "[init_network] ${1}"
}

function add_routes() {
	a[0]=0.0.0.0
	a[1]=1.0.0.0
	a[2]=3.0.0.0
	a[3]=7.0.0.0
	a[4]=15.0.0.0
	a[5]=31.0.0.0
	a[6]=63.0.0.0
	a[7]=127.0.0.0
	a[8]=255.0.0.0
	a[9]=255.1.0.0
	a[10]=255.3.0.0
	a[11]=255.7.0.0
	a[12]=255.15.0.0
	a[13]=255.31.0.0
	a[14]=255.63.0.0
	a[15]=255.127.0.0
	a[16]=255.255.0.0
	a[17]=255.255.1.0
	a[18]=255.255.3.0
	a[19]=255.255.7.0
	a[20]=255.255.15.0
	a[21]=255.255.31.0
	a[22]=255.255.63.0
	a[23]=255.255.127.0
	a[24]=255.255.255.0
	a[25]=255.255.255.1
	a[26]=255.255.255.3
	a[27]=255.255.255.7
	a[28]=255.255.255.15
	a[29]=255.255.255.31
	a[30]=255.255.255.63
	a[31]=255.255.255.127
	a[32]=255.255.255.255

	routing=$(/usr/fallback/beroconf get root routing | grep -v failed)

	IFS=,
	for i in $routing ; do
		net=$(echo $i | cut -d "/" -f1)
		netmask_bits=$(echo $i | cut -d "/" -f2)
		netmask=${a[$netmask_bits]}
		gateway=$(echo $i | cut -d "/" -f3)
		log "Adding: route add -net $net netmask $netmask gw $gateway"
		/sbin/route add -net $net netmask $netmask gw $gateway
	done
}

function setup_switch () {
	/sbin/mdio f 0:1600 > /dev/null
	/sbin/mdio w 0:0:6:5:128 > /dev/null
	/sbin/mdio w 0:0:14:16:4 > /dev/null
	/sbin/mdio w 0:0:7:0:2 > /dev/null
	/sbin/mdio w 0:0:7:16:2 > /dev/null
	/sbin/mdio w 0:0:7:4:10 > /dev/null
	/sbin/mdio w 0:0:7:20:11 > /dev/null
	/sbin/mdio w 0:0:15:14:20 > /dev/null
	/sbin/mdio w 0:0:15:15:2 > /dev/null
	/sbin/mdio w 0:0:15:20:100 > /dev/null
	/sbin/mdio w 0:0:15:18:13 > /dev/null
	/sbin/mdio w 0:0:15:14:4 > /dev/null
	/sbin/mdio w 0:0:15:15:2 > /dev/null
	/sbin/mdio w 0:0:6:1:67 > /dev/null
}

function conf_lan_wan () {
	# get eth0 up for vlan to work
	/sbin/ifconfig eth0 0.0.0.0 up

	# configure switch-side
	setup_switch

	# configure gateway-side
	/sbin/insmod /lib/modules/8021q.ko
	/sbin/ifup eth0.10
	/sbin/ifup eth0.11

	# netconfig server on lan needs this:
	route add 255.255.255.255 eth0.10

	# enable routing
	echo 1 > /proc/sys/net/ipv4/ip_forward
}

function deconf_lan_wan () {
	# disable routing
	echo 0 > /proc/sys/net/ipv4/ip_forward

	# deconfigure interfaces
	/sbin/ifdown eth0.10
	/sbin/ifdown eth0.11
	/sbin/rmmod /lib/modules/8021q.ko

	/sbin/ifconfig eth0 down
}

function conf_lan_bonding () {
	# get eth0 up for vlan to work
	/sbin/ifconfig eth0 0.0.0.0 up

	# configure switch-side
	setup_switch

	# configure gateway-side
	/sbin/insmod /lib/modules/8021q.ko
	/sbin/vconfig add eth0 10
	/sbin/vconfig add eth0 11

	# get bonding-parameters
	# 0 for balance-rr, 1 for active-backup, 2 for balance-xor, 3 for broadcast, 4 for 802.3ad, 5 for balance-tlb, 6 for balance-alb
	bond_mode=$(/usr/fallback/beroconf get root bonding-mode | grep -v failed)
	if [ -z "${bond_mode}" ]; then
		bond_mode=1
	fi

	bond_miimon=$(/usr/fallback/beroconf get root bonding-miimon | grep -v failed)
	if [ -z "${bond_miimon}" ]; then
		bond_miimon=100
	fi

	bond_updelay=$(/usr/fallback/beroconf get root bonding-updelay | grep -v failed)
	if [ -z "${bond_updelay}" ]; then
		bond_updelay=200
	fi

	bond_downdelay=$(/usr/fallback/beroconf get root bonding-downdelay | grep -v failed)
	if [ -z "${bond_downdelay}" ]; then
		bond_downdelay=200
	fi

	# bring up interfaces
	/sbin/insmod /lib/modules/bonding.ko mode=${bond_mode} miimon=${bond_miimon} updelay=${bond_updelay} downdelay=${bond_downdelay}
	/sbin/ifconfig eth0.10 0.0.0.0 up
	/sbin/ifconfig eth0.11 0.0.0.0 up
	/sbin/ifconfig bond0 0.0.0.0 up

	# add vlan-devices to it
	/sbin/ifenslave bond0 eth0.10 eth0.11

	# configure interface
	/sbin/ifup bond0
}

function deconf_lan_bonding () {
	# deconfigure bonding interface
	/sbin/ifdown bond0

	# deconfigure interfaces
	/sbin/ifconfig eth0.10 down
	/sbin/ifconfig eth0.11 down
	/sbin/rmmod /lib/modules/bonding.ko
	/sbin/rmmod /lib/modules/8021q.ko

	/sbin/ifconfig eth0 down
}

function conf_lan_single () {

	# okay, we start with the default settings depending on how many lan-ports we have
	case "$(/usr/fallback/beroconf get root lan-ports | grep -v failed)" in
		1)
			iface="eth0"
			/sbin/ifconfig eth0 10.0.0.2 netmask 255.0.0.0 up
			/sbin/route add default eth0
			;;
		2)
			iface="eth0.10"
			setup_switch
			/sbin/ifconfig eth0 0.0.0.0 up
			/sbin/insmod /lib/modules/8021q.ko
			;;
	esac

	# bring up interface
	/sbin/ifup ${iface}
}

function deconf_lan_single () {
	lan_ports=$(/usr/fallback/beroconf get root lan-ports | grep -v failed)
	iface="eth0"
	if [ "${lan_ports}" = "2" ]; then
		iface="${iface}.10"
	fi

	/sbin/ifdown ${iface}
	if [ "${lan_ports}" = "2" ]; then
		/sbin/rmmod /lib/modules/8021q.ko
	fi
}

function conf_lan_single_vlan () {
	# get eth0 up for vlan to work
	/sbin/ifconfig eth0 0.0.0.0 up

	# get the vlan-ids
	vlan_id=$(/usr/fallback/beroconf get root vlan-id | grep -v failed)

	# configure interface
	/sbin/insmod /lib/modules/8021q.ko
	/sbin/ifup eth0.${vlan_id}
}

function deconf_lan_single_vlan () {
	# get the vlan-ids
	vlan_id=$(/usr/fallback/beroconf get root vlan-id | grep -v failed)

	# deconfigure interface
	/sbin/ifdown eth0.${vlan_id}
	/sbin/rmmod /lib/modules/8021q.ko

	/sbin/ifconfig eth0 down
}

function eval_lan_ports () {

	# old gateways always have one port
	gateway_hw=$(cat /sys/class/beronet/gateway/type)
	if [ ${gateway_hw} -lt 30 ]; then
		/usr/fallback/beroconf set root lan-ports 1
		log "Detected Network-Ports: 1"
		return
	fi

	# get current lan-port-count to check if something has changed
	lan_ports=$(/usr/fallback/beroconf get root lan-ports | grep -v failed)
	if [ -z "${lan_ports}" ]; then
		lan_ports=1
	fi

	/sbin/ifup eth1
	sleep 2
	/sbin/mdio f 0:1600 > /dev/null
	phy_id_lb_1=$(expr match "$(/sbin/mdio r 0:0:0:2)" ".*register_value=\([0-9]*\)")

	if [ -z "${phy_id_lb_1}" ]; then
		/usr/fallback/beroconf set root lan-ports 1
		log "Detected Network-Ports: 1"
		return
	fi

	# we always reset lan-mode if count of ports has changed
	if [ ${phy_id_lb_1} -ne 65535 ]; then
		if [ ${lan_ports} -eq 2 ]; then
			/usr/fallback/beroconf set root lan-mode single
		fi
		/usr/fallback/beroconf set root lan-ports 1
		log "Detected Network-Ports: 1"
		return
	fi

	if [ ${lan_ports} -eq 1 ]; then
		/usr/fallback/beroconf set root lan-mode single
	fi
	/usr/fallback/beroconf set root lan-ports 2
	log "Detected Network-Ports: 2"
}

function start_network () {


	#load modules if necessary, will be unloaded then at the end of this function
	lsmod|grep berofix_driver &> /dev/null
	if [[ $? != 0 ]]; then
		need_load_berofix_driver=1
		insmod /lib/modules/berofix-driver.ko
	fi

	lsmod|grep csmencaps &> /dev/null
	if [[ $? != 0 ]]; then
		need_load_csmencaps=1
		insmod /lib/modules/csmencaps.ko
	fi

	# if lan-mode is not set, we need to initialize it
	eval_lan_ports

	# update /etc/network/interfaces
	/usr/fallback/update-interfaces

	# make sure eth1 has the address configured
	/sbin/ifdown eth1; /sbin/ifup eth1

	# evaluate lan-mode and configure accordingly
	lan_mode=$(/usr/fallback/beroconf get root lan-mode | grep -v failed)
	if [ -z "${lan_mode}" ]; then
		lan_mode=single
	fi
	log "Configuring network for mode: ${lan_mode}"
	case "${lan_mode}" in
		lan-wan)
			conf_lan_wan
			;;
		bonding)
			conf_lan_bonding
			;;
		single)
			vlan=$(/usr/fallback/beroconf get root vlan-enable | grep -v failed)
			if [ "${vlan}" = "1" ]; then
				conf_lan_single_vlan
			else
				conf_lan_single
			fi
			;;
	esac

	[[ "$need_load_berofix_driver" = 1 ]] && rmmod berofix-driver.ko
	[[ "$need_load_csmencaps" = 1 ]] && rmmod csmencaps

	add_routes
}

function stop_network () {
	# evaluate lan-mode and deconfigure accordingly
	lan_mode=$(/usr/fallback/beroconf get root lan-mode | grep -v failed)
	log "Deconfiguring network for mode: ${lan_mode}"
	case "${lan_mode}" in
		lan-wan)
			deconf_lan_wan
			;;
		bonding)
			deconf_lan_bonding
			;;
		*)
			vlan=$(/usr/fallback/beroconf get root vlan-enable | grep -v failed)
			if [ "${vlan}" = "1" ]; then
				deconf_lan_single_vlan
			else
				deconf_lan_single
			fi
			;;
	esac
}

### main ###
case "${1}" in
	start)
		start_network
		;;
	stop)
		stop_network
		;;
	restart|reload)
		stop_network
		start_network
		;;
	*)
		echo "Usage: ${0} {start|stop|restart|reload}" >&2
		exit 1
esac
