#!/bin/bash

# $Id: initconf 864 2006-06-11 11:16:23Z pilot $
# This script is expected to automatically create the first interface
# configuration directories and files in case there are no existing ones
# in /etc/net/ifaces.
# Expected to detect: ethernet (static/dhcp/ipv4ll) and IP tunnels,
# IPv4 addresses and static routes.

IFACEDIR=${IFACEDIR:-/etc/net/ifaces}
if [ "$1" = "write" ]; then
	TESTMODE=no
	[ -d "$IFACEDIR" ] || {
		echo "ERROR: $IFACEDIR does not exist, exiting"
		exit 1
	}
fi

[ -x ${IP:=/sbin/ip} ] || {
	echo "ERROR: $IP is not available, exiting"
	exit 1
}

[ -x ${ETHTOOL:=/usr/sbin/ethtool} ] || echo "WARNING: $ETHTOOL is not available, module detection will be skipped"

IFTAB=/etc/net/iftab
OLDCFG="/etc/sysconfig/network-scripts/ifcfg"

function store()
{
	local FILENAME=${1:?missing 1st arg to $FUNCNAME}
	local FILELINE=${2:?missing 2nd arg to $FUNCNAME}
	if [ "$TESTMODE" != "no" ]; then
		echo "TEST: will write to file $FILENAME:"
		echo '--------8<--------8<--------8<--------8<'
		echo -e "$FILELINE"
		echo '--------8<--------8<--------8<--------8<'
	else
		echo -e "$FILELINE" >> $FILENAME
	fi
}

function makedir()
{
	local DIRNAME=${1:?missing 1st arg to $FUNCNAME}
	if [ "$TESTMODE" != "no" ]; then
		echo "TEST: will create directory $DIRNAME:"
	else
		mkdir $DIRNAME
	fi
}

# broadcast multiple access
function print_ipv4_BMA_addresses()
{
	local IFNAME=${1:?missing 1st arg to $FUNCNAME}
	$IP -4 ad sh dev $IFNAME | grep '^ *inet' | sed 's/^ *inet //' | cut -d' ' -f1 | tr '\n' '\t' | sed 's/\t/ NEWLINE /g' | sed 's/ NEWLINE /\\n/g'
}

# peer-to-peer
function print_ipv4_P2P_addresses()
{
	local IFNAME=${1:?missing 1st arg to $FUNCNAME}
	$IP -4 ad sh dev $IFNAME | grep '^ *inet' | sed 's/^ *inet //' | cut -d' ' -f1-3 | tr '\n' '\t' | sed 's/\t/ NEWLINE /g' | sed 's/ NEWLINE /\\n/g'
}

for iface in `$IP li | egrep '^[[:digit:]]+: ' | cut -d' ' -f2 | sed 's/://' | sed 's/@.*$//'`; do
	echo -n "Processing interface '$iface':"
	if [ -d $IFACEDIR/$iface ]; then
		echo " configuration exists"
		continue
	fi
	if [ "$iface" = "gre0" -o "$iface" = "tunl0" ]; then
		echo " skipped pseudo-interface"
		continue
	fi
	unset LINKTYPE OLDPROTO BOOTPROTO LLADDR MODULE IPV4ADDRS IPV4ROUTES
	LINKTYPE=`$IP li sh dev $iface | fgrep 'link/' | sed 's/^ *link\///' | cut --delimiter=' ' --fields=1`
	if [ -n "$LINKTYPE" ]; then
		# try to find linktype-specific options
		case "$LINKTYPE" in
			ether)
				# detect BOOTPROTO
				if [ -s "$OLDCFG-$iface" ]; then
					OLDPROTO="`grep ^[[:space:]]*BOOTPROTO= $OLDCFG-$iface | cut -f2 -d=`"
					# map old name to new one
					case $OLDPROTO in
						dhcp|DHCP) BOOTPROTO="dhcp";;
						zcip|ZCIP) BOOTPROTO="ipv4ll";;
					esac
				fi
				# many others try to look as ethernet, so let's filter by iface name...
				if [ "${iface//[0-9]*/}" = "eth" ]; then
					# find and use link-level address
					LLADDR=`$IP li sh dev $iface | fgrep 'link/ether' | sed 's/^ *link\/ether //' | cut --delimiter=' ' --fields=1`
					# ...and by valid MAC address
					if [ "$LLADDR" != "00:00:00:00:00:00" ]; then
						store $IFTAB "# Generated by /etc/net initconf script\n$iface mac $LLADDR\n"
					fi
					makedir $IFACEDIR/$iface
					store $IFACEDIR/$iface/options "# If you want to change current interface name, edit $IFTAB,\n# rename current directory and uncomment this line:\n#TYPE=eth\n"
					# find module
					if [ -x "$ETHTOOL" ]; then
						MODULE=`ethtool -i $iface | fgrep 'driver: ' | cut -d' ' -f2`
						if [ -n "$MODULE" ]; then
							store $IFACEDIR/$iface/options "# Uncomment this line if you don't have modules.conf alias for this interface\n# and don't intend to use hotplug configuration.\n#MODULE=$MODULE\n"
							store $IFTAB "# Generated by /etc/net initconf script\n#$iface driver $MODULE\n"
						fi
					fi
				fi
				if [ -n "$BOOTPROTO" ]; then
					store $IFACEDIR/$iface/options "BOOTPROTO=$BOOTPROTO"
				else
					IPV4ADDRS=`print_ipv4_BMA_addresses $iface`
				fi
			;;
			gre|ipip)
				store $IFACEDIR/$iface/options "TUNTYPE=$LINKTYPE"
				CARRIER_LOCAL=`ip tu sh $iface | sed 's/  /\n/g' | grep '^local ' | cut -d' ' -f2`
				CARRIER_REMOTE=`ip tu sh $iface | sed 's/  /\n/g' | grep '^remote ' | cut -d' ' -f2`
				[ -n "$CARRIER_LOCAL" ] && store $IFACEDIR/$iface/options "TUNLOCAL=$CARRIER_LOCAL"
				[ -n "$CARRIER_REMOTE" ] && store $IFACEDIR/$iface/options "TUNREMOTE=$CARRIER_REMOTE"
				IPV4ADDRS=`print_ipv4_P2P_addresses $iface`
			;;
		esac
	fi
	if [ -n "$IPV4ADDRS" ]; then
		store $IFACEDIR/$iface/ipv4address "$IPV4ADDRS"
		IPV4ROUTES=`$IP -4 ro ls dev $iface type unicast scope global | fgrep -v 'proto zebra' | tr '\n' '\t' | sed 's/\t/ NEWLINE /g' | sed 's/ NEWLINE /\\\\n/g'`
		[ -n "$IPV4ROUTES" ] && store $IFACEDIR/$iface/ipv4route "$IPV4ROUTES"
	fi
	echo ' finished'
done
