#!/bin/sh
# vim: set ts=4 sw=4:
#
# Note: This script should work also on Debian, they uses the same
# configuration format as Alpine.
set -eu

readonly DEFAULT_MASK='255.255.255.0'

# Prints address (a.b.c.1) of the default gateway for the given IPv4 address.
# This is used for ETH0 interface when ETH0_GATEWAY is not provided.
gen_gateway_from_ipv4() {
	local ip="$1"

	echo "$(echo $ip | cut -d. -f1-3).1"
}

# Prints name of the context managed interface for the given MAC address.
# The name is in upper case and used as a prefix for variables that defines
# this interface. Returns empty string if doesn't exist.
context_dev_by_mac() {
	local mac="$1"

	env | sed -En "s/^(ETH[0-9]+)_MAC=$mac/\1/p"
}

# Prints the value of each variable matching the specified regex.
#
# $1: Grep regexp.
getvals() {
	local regexp="$1"

	local var; for var in $(env | sed -En "s/^($regexp)=\S.*/\1/p" | sort); do
		getval "$var"
	done
}

# Generates and prints configuration for the specified network interface.
#
# $1: Device name of the interface (e.g. eth0, eth1).
# $2: Context name of the interface, i.e. variable prefix (e.g. ETH0, ETH1).
gen_iface_conf() {
	local dev="$1"
	local prefix="$2"

	local ip4="$(getval "$prefix"_IP)"
	local ip6="$(getval "$prefix"_IP6 "$(getval "$prefix"_IPV6)")"  # _IPV6 is deprecated
	local gw6="$(getval "$prefix"_GATEWAY6)"

	echo "auto $dev"

	if [ "$ip4" ]; then
		local netmask4="$(getval "$prefix"_MASK "$DEFAULT_MASK")"

		local gw4="$(getval "$prefix"_GATEWAY)"
		if [ -z "$gw4" ] && [ "$prefix" = 'ETH0' ]; then
			gw4="$(gen_gateway_from_ipv4 "$ip4")"
		fi

		cat <<-EOF
			iface $dev inet static
			    address $ip4
			    netmask $netmask4
		EOF
		[ -z "$gw4"  ] || echo "    gateway $gw4"
	fi

	if [ "$ip6" ] && [ "$gw6" ]; then
		[ -z "$ip4" ] || printf '\n'
		cat <<-EOF
			iface $dev inet6 static
			    address ${ip6%/*}
			    netmask ${ip6#*/}
		EOF
		[ -z "$gw6"  ] || echo "    gateway $gw6"
		echo "    pre-up echo 0 > /proc/sys/net/ipv6/conf/$dev/accept_ra"
	fi

	if [ -z "${ip4}${ip6}${gw6}" ]; then
		echo "iface $dev inet dhcp"  # fallback to DHCP
	fi
}

# Generates and prints configuration for all the contextualized
# network interfaces.
gen_network_conf() {
	local dev mac prefix

	for dev in $(ls /sys/class/net); do
		mac="$(cat /sys/class/net/$dev/address)" 2>/dev/null || continue
		prefix="$(context_dev_by_mac "$mac")"

		if [ "$prefix" ]; then
			gen_iface_conf "$dev" "$prefix"
			echo ''
		fi
	done
}

# Generates and prints resolv.conf with DNS and SEARCH_DOMAIN collected from
# all contextualized network interfaces.
gen_resolv_conf() {
	local item search=''

	for item in ${SEARCH_DOMAIN:-} $(getvals 'ETH[0-9]+_SEARCH_DOMAIN'); do
		search="$search $item"
	done
	[ -z "$search" ] || echo "search $search"

	for item in ${DNS:-} $(getvals 'ETH[0-9]+_DNS'); do
		echo "nameserver $item"
	done
}


#-------------------------------- Main -------------------------------

. "$(dirname "$(readlink -f "$0")")/utils.sh"

if ! yesno "${NETWORK:-}"; then
	exit 0
fi

update_config '/etc/network/interfaces' "$(readlink -f $0)" "$(gen_network_conf)"

resolv_conf="$(gen_resolv_conf)"
if [ "$resolv_conf" ]; then
	[ -L /etc/resolv.conf ] && rm /etc/resolv.conf
	echo "# Generated by $(readlink -f $0)" > /etc/resolv.conf
	echo "$resolv_conf" >> /etc/resolv.conf
fi

/etc/init.d/networking restart
