#!/bin/sh
# Early network configurator, in a silent way.
# Copyright (GNU GPL) Actiu.info
# Version 2023.09.19
# Tested in Debian 7, 8, 9, 10, 11, 12; Devuan 1
# Development at: pro/instals.gnu/utilitats_sh/nomes-servidors/initramfs_quiet_net

# Installation: Save and configure this script as
# /etc/initramfs-tools/scripts/init-top/initramfs_quiet_net
# (give it execution permissions)
# Then run: apt-get install dropbear busybox ; update-initramfs -u -k all

# TO DO:
#	- 

# NetConfigs syntax: different devices separated by blank space, and for each one: devname/ip/mask/gateway or devname/dhcp/timeout
# Note: gateway is only required for WAN device when no dhcp.
NetConfigs="eth0/dhcp/20 eth1/192.168.2.100/255.255.255.0/gatewayifwan"
SshPort=222
DropbearTimeout=5
ReleaseNICsAtEnd=1
LogLevel=2	# 0=Nothing 1=Errors 2=Warnings+E 3=Info+W+E 4=Debug

PREREQ="udev"

prereqs()
{
	echo "$PREREQ"
}

case $1 in
# get pre-requisites
prereqs)
	prereqs
	exit 0
	;;
esac

# PENDIENTE:
#	- Esperar 5 minutos a la configuracion exitosa; sino reiniciar el sistema con /bin/reboot
#	  (como cliente DHCP, ante un fallo de ISP, dispositivo remoto o cable, a los ~2 minutos se desiste!)
#	- Admitir como dispositivo "all/dhcp" para recorrer todos los existentes.

UpDhcp ()
{
	local Device="$1"
	local Method="$2"
	local Timeout="$3"
	local DhClient=""
	local CurrentDir=""
	local Result=0
	local ResultN=0
	
	if [ "$Timeout" = "" ] ; then Timeout=36 ; fi
	if [ -x /usr/bin/dhclient ] ; then DhClient="/usr/bin/dhclient" ; fi
	if [ -x /usr/sbin/dhclient ] ; then DhClient="/usr/sbin/dhclient" ; fi
	if [ -x /bin/dhclient ] ; then DhClient="/bin/dhclient" ; fi
	if [ -x /sbin/dhclient ] ; then DhClient="/sbin/dhclient" ; fi
	for CurrentDir in $(printf '%s\n' "$PATH" | tr -s ':' ' ') ; do
		if [ -x "${CurrentDir}/dhclient" ] ; then DhClient="${CurrentDir}/dhclient" ; fi
	done
	if [ "$DhClient" != "" ] ; then
		if [ $LogLevel -ge 4 ] ; then
			LogProgram 4 '$' "$DhClient" $Device
			"$DhClient" $Device
			Result=$? ; if [ $ResultN -eq 0 ] ; then ResultN=$Result ; fi
		else
			"$DhClient" $Device > /dev/null 2>&1
			Result=$? ; if [ $ResultN -eq 0 ] ; then ResultN=$Result ; fi
		fi
	else
		if [ $LogLevel -ge 4 ] ; then
			LogProgram 4 '$' ipconfig -t $Timeout -c $Method -d $Device
			ipconfig -t $Timeout -c $Method -d $Device
			Result=$? ; if [ $ResultN -eq 0 ] ; then ResultN=$Result ; fi
		else
			ipconfig -t $Timeout -c $Method -d $Device > /dev/null 2>&1
			Result=$? ; if [ $ResultN -eq 0 ] ; then ResultN=$Result ; fi
		fi
	fi
	return $ResultN
}

UpStatic ()
{
	local Device="$1"
	local Ip="$2"
	local Netmask="$3"
	local Gateway="$4"
	local Result=0
	local ResultN=0
	
	if [ "$Netmask" = "" ] ; then Netmask="255.255.255.0" ; fi
	if [ $LogLevel -ge 4 ] ; then
		LogProgram 4 '$' ifconfig $Device $Ip netmask $Netmask
		ifconfig $Device $Ip netmask $Netmask
		Result=$? ; if [ $ResultN -eq 0 ] ; then ResultN=$Result ; fi
	else
		ifconfig $Device $Ip netmask $Netmask > /dev/null 2>&1
		Result=$? ; if [ $ResultN -eq 0 ] ; then ResultN=$Result ; fi
	fi
	if [ "$Gateway" != "" ] ; then
		if [ $LogLevel -ge 4 ] ; then
			LogProgram 4 '$' route add default gw $Gateway dev $Device
			route add default gw $Gateway dev $Device
			Result=$? ; if [ $ResultN -eq 0 ] ; then ResultN=$Result ; fi
		else
			route add default gw $Gateway dev $Device > /dev/null 2>&1
			Result=$? ; if [ $ResultN -eq 0 ] ; then ResultN=$Result ; fi
		fi
	fi
	return $ResultN
}

UpDevice ()
{
	local DeviceData="$1"
	local Result=0
	local ResultN=0
	
#	if [ "$(printf '%s\n' "$DeviceData" | grep -ie /dhcp/)" = "" ] && [ "$(printf '%s\n' "$DeviceData" | grep -ie /bootp/)" = "" ] && [ "$(printf '%s\n' "$DeviceData" | grep -ie /rarp/)" = "" ] && [ "$(printf '%s\n' "$DeviceData" | grep -ie /both/)" = "" ] ; then
	if [ "$(printf '%s\n' "$DeviceData" | grep -ie /dhcp/ -ie /bootp/ -ie /rarp/ -ie /both/)" = "" ] ; then
		DeviceData="$(printf '%s\n' "$DeviceData" | tr -s '/' ' ')"
		LogProgram 4 '$$' UpStatic $DeviceData
		UpStatic $DeviceData
		Result=$? ; if [ $ResultN -eq 0 ] ; then ResultN=$Result ; fi
	else
		DeviceData="$(printf '%s\n' "$DeviceData" | tr -s '/' ' ')"
		LogProgram 4 '$$' UpDhcp $DeviceData
		UpDhcp $DeviceData
		Result=$? ; if [ $ResultN -eq 0 ] ; then ResultN=$Result ; fi
	fi
	return $ResultN
}

LogProgram ()
{
	local ThisLevel="$1"
	if [ $# -gt 0 ] ; then shift ; fi
	
	if [ "$*" != "" ] && [ $LogLevel -ge $ThisLevel ] ; then
		if [ $ThisLevel -ge 4 ] ; then
			printf '%s\n' "$*" 1>&2
		else
			printf '%s\n' "$*"
		fi
		if [ "$MainLog" != "" ] ; then
			mkdir -p "$(Dirname "$MainLog")"
			printf '%s\n' "$(date '+%Y-%m-%dT%T%z') $*" >> "$MainLog"
		fi
	fi
}


##### MAIN SCRIPT #####

Result=0
ResultN=0

for CurrentDevice in $NetConfigs ; do
	LogProgram 4 "\$\$ UpDevice $CurrentDevice"
	UpDevice $CurrentDevice
	Result=$? ; if [ $ResultN -eq 0 ] ; then ResultN=$Result ; fi
done

# Disabling default network autoconfiguration
if [ $ResultN -eq 0 ] ; then
	if [ "$(cat /scripts/init-premount/dropbear 2>/dev/null | grep -e 'configure_networking')" != "" ] ; then
		LogProgram 4 "# Disabling default network autoconfiguration"
		cat /scripts/init-premount/dropbear | grep -ve 'configure_networking' > /tmp/manual_net.tmp
		cat /tmp/manual_net.tmp > /scripts/init-premount/dropbear
		rm /tmp/manual_net.tmp
	fi
else
	LogProgram 3 "W: Network configuration cannot be quiet."
fi

# Changing port to Dropbear
if [ -f /scripts/init-premount/dropbear ] ; then
	LogProgram 4 "# Changing port for Dropbear to $SshPort"
	cat /scripts/init-premount/dropbear | sed -e "s|/dropbear -|/dropbear -p ${SshPort} -I ${DropbearTimeout} -|g" > /tmp/manual_net.tmp
	sed -i "s|/dropbear \$|/dropbear -p ${SshPort} -I ${DropbearTimeout} \$|g" /tmp/manual_net.tmp
	cat /tmp/manual_net.tmp | sed -e "s|dropbear$|dropbear -p ${SshPort} -I ${DropbearTimeout}|g" > /scripts/init-premount/dropbear
	rm /tmp/manual_net.tmp
else
	if [ "$SshPort" != "22" ] ; then
		LogProgram 1 "E: premount/dropbear script not found to change listening port."
		LogProgram 1 "   Note dropbear-initramfs package must be installed."
	fi
fi

# Writing a script to release NICs after
if [ "$ReleaseNICsAtEnd" != "0" ] ; then
	LogProgram 4 "# Writing a script to release NICs after"
	printf '%s\n' '#!/bin/sh' > /scripts/init-bottom/release_nics
	for CurrentDevice in $NetConfigs ; do
		CurrentName="$(printf '%s\n' "$CurrentDevice" | cut -f 1 -d '/')"
#		printf '%s\n' "ifconfig $CurrentName down" >> /scripts/init-bottom/release_nics
		if [ $LogLevel -ge 4 ] ; then
			printf '%s\n' "echo ip addr flush dev $CurrentName" >> /scripts/init-bottom/release_nics
		fi
		printf '%s\n' "ip addr flush dev $CurrentName" >> /scripts/init-bottom/release_nics
#		printf '%s\n' "ip link set $CurrentName down" >> /scripts/init-bottom/release_nics
	done
	chmod +x /scripts/init-bottom/release_nics
	if [ -x /scripts/init-bottom/dropbear ] ; then
		if [ $LogLevel -ge 4 ] ; then
			printf '%s\n' "# Appending release_nics call to init-bottom/dropbear"
			printf '%s\n' "echo /scripts/init-bottom/release_nics" >> /scripts/init-bottom/dropbear
		fi
		printf '%s\n' "/scripts/init-bottom/release_nics" >> /scripts/init-bottom/dropbear
	else
		if [ $LogLevel -ge 4 ] ; then
			printf '%s\n' "# Appending release_nics call to init-bottom/ORDER"
			printf '%s\n' "echo /scripts/init-bottom/release_nics" >> /scripts/init-bottom/ORDER
		fi
		printf '%s\n' "/scripts/init-bottom/release_nics" >> /scripts/init-bottom/ORDER
		chmod +x /scripts/init-bottom/ORDER
	fi
fi

LogProgram 4 "# Completing with exitcode: $ResultN"
exit $ResultN
