#!/bin/bash
#
# --------------------------------------------------------------------------
# Copyright notice
# --------------------------------------------------------------------------
# Copyright: Rene Mayrhofer, Jan. 2005
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; see the file COPYING.  If not, write to
# the Free Software Foundation, 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
# On Debian GNU/Linux systems, the complete text of the GNU General
# Public License can be found in `/usr/share/common-licenses/GPL'.
# --------------------------------------------------------------------------
#

# seconds to wait for the administrator when a network card was not found
DELAY=30
# number of pings to try
PINGS=4

. /usr/lib/gibraltar-bootsupport/common-definitions.sh

# this does only make sense if we are not in the unconfigured mode
[ -e /etc/unconfigured ] && exit 0

echo -n "Checking if all configured network interfaces could be loaded... "
error=0
failed_macs=""
working_macs=""
awk '/^ *mac .+:.+:.+:.+:.+:.+ *$/{print $2};' /etc/network/interfaces | \
while read mac_configured; do
  if ! ip link show | grep -q "$mac_configured"; then
    # this is an error - the MAC address specified in the config file is 
    # not used by of the loaded network adapters
    error=1
    failed_macs="$failed_macs $mac_configured"
  else
    working_macs="$working_macs $mac_configured"
  fi
done

if [ $error -eq 0 ]; then
  echo -e "${COLOR_GRREN}OK${COLOR_NORMAL}"
else
  # report the error to the user to let him decide
  echo -e "${COLOR_RED}failed${COLOR_NORMAL}"
  echo "MAC address(es) $failed_macs are no longer in the system"
  beepconsole -f 500 -l 200 -r 2 -d 200
  
  if [ -z "$working_macs" ]; then
    # but if we haven't found a single network adapter, there is no need to 
    # decide - it's the best to stop here and wait!
    echo -e "${COLOR_RED}Serious error:${COLOR_NORMAL} no network card found at all."
    echo "Stopping further bootup now."
    echo "Do you want to probe for new network cards now [y/n]?"
    wait=""
  else
    echo "Do you want to probe for new network cards now [y/n] (waiting for $DELAY seconds)?"
    wait="-t $DELAY"
  fi
  if read -n 1 -r -s; then
    # no timeout, the user has pressed a key
    if [ "$REPLY" = "y" ]; then
      /etc/setup.d/00network-cards
    else
      echo "Ok, not probing for new networks cards."
    fi
    echo
    
    # after probing for possible new network cards, now go through the list of
    # MAC addresses that are available to the system right now
    echo "Checking for MAC addresses not configured until now... "
    new_macs_found=0
    ip link | awk '/link\/ether/ {print $2};' | while read mac_available; do
      # for every such MAC addresses, check if it is "new" in the sense that
      # it has not been configured
      mac_pattern="^ *mac +$mac_available *$"
      if ! egrep -q "$mac_pattern" /etc/network/interfaces; then
        # yes, this is a new one
        new_macs_found=1
        echo -n "Found MAC '$mac_available'. Do you want to configure it now [y/n]? "
	if read -n 1 -r -s && [ "$REPLY" = "y" ]; then
	  # this is a bit tricky now - present the user a pseudo-menu to select
	  # an old MAC address to overwrite
	  while true; do
  	    echo "Which of the following old configured MAC addresses do you want to replace?"
	    i=0
	    for failed_mac in $failed_macs; do
	      let i=i+1
	      echo "[$i] $failed_mac"
	    done
	    echo "Please enter 1 to $i or hit Ctrl-D to abort."
	    echo
	    if read -n 1 -r -s; then
	      if [ $REPLY -ge 1 -a $REPLY -le $i ]; then
	        # get the appropriate MAC address
		replace_old_mac=`echo $failed_macs | cut -d' ' -f$REPLY`
		# and try to replace it
		echo "Trying to replace old address $replace_old_mac by new address $mac_available:"
		# first in /etc/network/interfaces
		echo "    modifying configuration"
		cp /etc/network/interfaces /etc/network/interfaces.save
		sed "s/mac $replace_old_mac/mac $mac_available" \
		  /etc/network/interfaces.save > /etc/network/interfaces
		# then try to activate this network interface
		# this is again a bit tricky - need to grep the interface name
		# out of /etc/network/interfaces - this is an ugly solution, 
		# but I don't know a better one with shell scripts :(
		echo -n "    activating network interface "
		# hack: go from the MAC line upwards until we hit a line 
		# starting with "iface"
		# I know that this can run into an endless loop with 
		# improperly formatted files, but if your file is that broken,
		# there's not much I can do about it here... 
		# TODO: at least fix the possible endless loop
		j=1
		while ! line=`egrep "$mac_pattern" -B $j \
		        /etc/network/interfaces | egrep "^iface"`; do
		  let j=j+1
		done
		iface=`echo $line | cut -d' ' -f2`
		echo -n "$iface... "
		if ifup $iface; then
		  echo -e -n "${COLOR_GREEN}OK${COLOR_NORMAL}, as "
		  newifacename=`ip link | grep -B 1 "$mac_available" | head -1 | cut -d':' -f2`
		  echo -n "$newifacename, with IP "
		  ip addr show $newifacename | awk '/inet / {print $2};'
		else
		  echo -e "${COLOR_RED}failed${COLOR_NORMAL}"
		  echo "    reverting configuration"
		  mv /etc/network/interfaces.save /etc/network/interfaces
		  # retry with possibly another MAC - jump back to the pseudo-menu loop
		  continue
		fi
		
		# now allow the user to ping some host as test
        	echo -n "Do you want to test it now [y/n]? "
		if read -n 1 -r -s && [ "$REPLY" = "y" ]; then
		  # set a network strict network policy that allows the box out but nothing in or through
		  echo "    setting firewalling policy for tests"
		  iptables -P INPUT DROP
		  iptables -P FORWARD DROP
		  iptables -P OUTPUT ACCEPT
		  iptables -F
		  iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
		  # now allow the ping
		  echo -n "   Please enter an IP address that should be reachable now: "
		  if read; then
		    if ping -c $PINGS -I $newifacename -n $REPLY; then
		      echo "The MAC address replacement seems to have worked."
		    else
		      echo "The test host could not be reached."
		    fi
		    echo -n "Do you want to keep this configuration [y/n]? "
		    if read -n 1 -r -s && [ "$REPLY" = "y" ]; then
		      echo "    OK, keeping this configuration."
		      # exit the pseudo-menu
		      break
		    else
		      echo "    reverting configuration"
		      mv /etc/network/interfaces.save /etc/network/interfaces
		      # retry with possibly another MAC - jump back to the pseudo-menu loop
		    fi
		  else
		    echo "cancelled"
		    echo "    reverting configuration"
		    mv /etc/network/interfaces.save /etc/network/interfaces
		    # retry with possibly another MAC - jump back to the pseudo-menu loop
		  fi
		else
		  # OK, the network interface came up OK but the user doesn't want to test
		  # just continue with the next MAC
                  # exit the pseudo-menu
	          break
		fi
	      else
	        echo "Invalid input, please enter a number from 1 to $i."
	      fi
	    else
	      echo "Cancelled"
	      break
	    fi
	  done
	fi
      fi
    done
    if [ new_macs_found -eq 0 ]; then
      echo "No new MAC addresses found, giving up."
      echo "Please check your hardware, it might show errors."
      echo "To continue bootup, please press Enter."
      read -s
    fi
  fi
fi

exit 0
