#!/bin/bash
#####################################################################
#
# Description:
#
# zSeries SE network adapter detection script used to detect and
# configure added network adapters.
#
# Change Activity:
#   10/19/2004 M. Clark         Initial creation
#   10/21/2004 M. Clark         Added hotplug startup
#   10/22/2004 M. Clark         Replaced exec_driver_activation_cmds
#                               with load_drivers to control which
#                               drivers get loaded
#   10/25/2004 M. Clark         Replace hotplug STARTMODE with onboot
#   11/18/2004 M. Clark         Don't exit if we find an unsupported card
#   01/25/2005 M. Clark         Added token ring support
#   03/29/2005 M. Clark         Added support Accton Technology card
#   05/20/2005 M. Clark         Change STARTMODE to manual for ifs beyond eth0
#   07/11/2005 M. Clark         Add check for marker file to allow DHCP
#   07/27/2005 M. Clark         Add hack to call setKeyboard and setLanguage
#   09/09/2005 M. Clark         Use xircom_cb driver instead of xircom_tulip_cb
#   09/22/2005 M. Clark         Use xircom_tulip_cb driver instead of xircom_cb
#   03/17/2006 M. Clark         Add support for Abocom PCI-Express card
#   06/19/2006 M. Clark         Add '109a' device id for e1000
#   06/27/2006 M. Clark         Add support for SMC USB 10/100 ethernet
#   08/02/2006 M. Clark         Change SMC USB driver to usbnet
#   10/25/2006 M. Clark         Add VLAN support
#   11/02/2006 M. Clark         Look in a few places for no_vlan_support
#   02/07/2007 M. Clark         Overwrite ifcfg-eth0 every time if we are vlan
#   02/07/2007 M. Clark         Don't modify anything if we're non-vlan
#   05/29/2007 M. Clark         Repurposed for use on ZHMC
#   08/07/2007 M. Clark         Set default IPv6 settings for autoconf/privext
#   09/24/2007 M. Clark         Added bnx2 support
#   10/19/2007 M. Clark         Delete the udev persistent names file
#   10/23/2007 M. Clark         Add device id 0x165a to tg3 list
#   11/16/2007 M. Clark         Process persistent net names file to ensure good ordering
#   02/13/2008 M. Clark         Added 0x105e and 0x1049 to e1000 device list
#   05/08/2008 M. Clark         Add logic to prevent multiple reboots
#   11/04/2008 M. Clark         Add support for Intel onboard PCI-Express cards
#
#####################################################################

#
# Functions
#
write_default_config() {
    local config_file=$1

    echo "Writing config file $config_file" >> $LOG

    echo "BOOTPROTO='static'" > $config_file
    echo "IPADDR='0.0.0.0'" >> $config_file
    echo "NETMASK='255.255.255.0'" >> $config_file
    echo "MTU='1500'" >> $config_file
    echo "STARTMODE='manual'" >> $config_file
}

load_drivers() {
    echo "-> load_drivers()" >> $LOG

    local i=0
    for id in $(grep "\<Vendor\>" $hwinfo_output | sed -e "s/.*0x/0x/;s/ .*$//"); do
        vendor_ids[$i]=$id
        i=$(($i+1))
    done

    i=0
    for id in $(grep "\<Device\>" $hwinfo_output | sed -e "s/.*0x/0x/;s/ .*$//"); do
        device_ids[$i]=$id
        i=$(($i+1))
    done

    if [ $i -gt 0 ]; then
        num_devices=$i

        i=0
        while [ $i -lt $num_devices ]; do
            echo "Found network card with Vendor Id: ${vendor_ids[$i]} Device Id: ${device_ids[$i]}" >> $LOG

            line=$(grep "^${vendor_ids[$i]}" $device_table | grep -m 1 "${device_ids[$i]}")
            if [ -n "$line" ]; then
                # found the device
                driver=$(echo $line | cut -d ':' -f 4)
                description=$(echo $line | cut -d ':' -f 5)
                echo "Loading $driver module for $description" >> $LOG
                modprobe $driver >> $LOG 2>&1
            else
                echo "Unsupported network card found." >> $LOG
            fi

            i=$(($i+1))
        done
    fi

    echo "<- load_drivers()" >> $LOG
}

#
# Global vars
#
LOG="/var/log/detectNetCards.log"
backup_dir="/etc/sysconfig/network/saved-configs"
hwinfo_output="/tmp/hwinfo.out"
device_table="/tmp/detectNetCards.table"
persist_file="/etc/udev/rules.d/30-net_persistent_names.rules"
new_persist_file="/tmp/new_persistent_names"
if [ -e /console/data/network ]; then
    network_data_dir="/console/data/network"
elif [ -e /opt/ccfw/data/network ]; then
    network_data_dir="/opt/ccfw/data/network"
fi

#
# Create the supported device table
#
cat > $device_table <<END
0x8086:0x10f5:eth:e1000e:Intel PCI-Express Gigabit Ethernet
0x8086:0x1000 0x1001 0x1004 0x1008 0x1009 0x100c 0x100d 0x100e 0x100f 0x1010 0x1011 0x1012 0x1013 0x1014 0x1015 0x1016 0x1017 0x1018 0x1019 0x101d 0x101e 0x1026 0x1027 0x1028 0x1075 0x1076 0x1077 0x1078 0x1079 0x107a 0x107b 0x109a 0x105e 0x1049:eth:e1000:Intel Gigabit
0x8086:0x1229 0x2449 0x1059 0x1209 0x1029 0x1030 0x1031 0x1032 0x1033 0x1034 0x1038 0x1039 0x103a 0x103b 0x103c 0x103d 0x103e 0x1050 0x1051 0x1052 0x1053 0x1054 0x1055 0x2459 0x245d:eth:e100:Intel 10/100
0x1011:0x0009:eth:tulip:DEC 21140 ethernet
0x1014:0x003e:tr:olympic ringspeed=16:IBM Tokenring
0x115d:0x0003:eth:xircom_tulip_cb:Xircom PCMCIA ethernet
0x14e4:0x1644 0x1645 0x1646 0x1647 0x164d 0x16a6 0x16a7 0x16a8 0x16c6 0x16c7 0x1648 0x1653 0x1654 0x1659 0x165d 0x165e 0x1696 0x167d 0x165a:eth:tg3:Broadcom Gigabit
0x14e4:0x164c:eth:bnx2:Broadcom NetXtreme II Gigabit
0x1113:0x1211:eth:8139too:Accton Gigabit
0x11ab:0x4362:eth:sk98lin:Abocom Systems Inc Gigabit
0x13b1:0x0018:eth:usbnet:Linksys USB 10/100 Network Adapter
0x0b95:0x1720:eth:usbnet:SMC USB 10/100 Network Adapter
0x1022:0x2000:eth:pcnet32:VMWare ethernet
END

#
# Execution start
#
rm -f $LOG
echo "Running detectNetCards at $(date)" > $LOG

echo "Executing hardware information utility" >> $LOG
/usr/sbin/hwinfo --netcard > $hwinfo_output

# Load the drivers for all installed cards
load_drivers

# Now check for the cards in /etc/udev/rules.d/30-net_persistent_names.rules
if [ "$network_data_dir" != "" ]; then
    installed_cards_file="$network_data_dir/installed_cards"
    new_installed_cards_file="/tmp/installed_cards"
    if [ -e "$persist_file" ]; then
        need_reboot="0"
        if [ -e "$installed_cards_file" ]; then
            while read line; do
                if [ "${line:0:9}" = "SUBSYSTEM" ]; then
                    mac=${line:50:17}
                    ifname=${line:107:4}

                    echo "Checking $ifname - $mac from persistent names file" >> $LOG

                    if ip link show | grep -q "$mac"; then
                        echo "Card $mac is still installed" >> $LOG
                        if grep -q "$mac" $installed_cards_file; then
                            our_ifname=$(grep "$mac" $installed_cards_file | sed -e 's/=.*//')
                            echo "Card $mac was installed as $our_ifname before." >> $LOG

                            if [ "$ifname" != "$our_ifname" ]; then
                                echo "Udev assigned a different id than we had previously.. need to reboot" >> $LOG
                                need_reboot="1"
                            else
                                echo "No id change detected.. no need to reboot" >> $LOG
                            fi

                            # Add to the files with ifname from installed_cards
                            echo "SUBSYSTEM==\"net\", ACTION==\"add\", SYSFS{address}==\"$mac\", IMPORT=\"/lib/udev/rename_netiface %k $our_ifname\"" >> $new_persist_file
                            echo "$our_ifname=$mac" >> $new_installed_cards_file
                        else
                            echo "Card $mac was *not* installed before.. let's find the best id for it." >> $LOG
                            i=0
                            while ip link show "eth$i" >&- 2>&-; do
                                if ip link show "eth$i" | grep -q "$mac"; then
                                    break;
                                fi
                                i=$((i+1))
                            done
                            echo "It looks like eth$i is the first available id" >> $LOG
                            if [ $i -lt ${ifname#eth} ]; then
                                echo "Found a better id than udev did.. need to reboot to apply" >> $LOG
                                echo "SUBSYSTEM==\"net\", ACTION==\"add\", SYSFS{address}==\"$mac\", IMPORT=\"/lib/udev/rename_netiface %k eth$i\"" >> $new_persist_file
                                echo "eth$i=$mac" >> $new_installed_cards_file
                                need_reboot="1"
                            else
                                echo "Udev assigned the best id.. no need to reboot" >> $LOG
                                echo "SUBSYSTEM==\"net\", ACTION==\"add\", SYSFS{address}==\"$mac\", IMPORT=\"/lib/udev/rename_netiface %k $ifname\"" >> $new_persist_file
                                echo "$ifname=$mac" >> $new_installed_cards_file

                            fi
                        fi
                    else
                        echo "Didn't find card $mac.. not putting this in new persistent names file" >> $LOG
                    fi
                fi
            done < $persist_file

            mv -f $new_persist_file $persist_file
            mv -f $new_installed_cards_file $installed_cards_file

            echo "Done processing persistent names file" >> $LOG

            if [ "$need_reboot" != "0" ]; then
                if [ -e "/tmp/.detectNetCards.rebooting" ]; then
                    echo "Trying to reboot twice in a row.. something is wrong" >> $LOG
                    tar czf "$network_data_dir/detectNetCards-debug-data.tgz" $persist_file $installed_cards_file /var/log/detectNetCards.lastlog $LOG
                    rm -f $persist_file /tmp
                    rm -f $installed_cards_file /tmp
                else
                    touch /tmp/.detectNetCards.rebooting
                    echo "Need to reboot to apply changes" >> $LOG
                    cp $LOG /var/log/detectNetCards.lastlog
                    echo ""
                    echo "*** Network card detection script has detected a change that requires a reboot ***"
                    echo ""
                    echo "Rebooting..."
                    reboot
                fi
            else
                if [ -e "/tmp/.detectNetCards.rebooting" ]; then
                    rm -f /tmp/.detectNetCards.rebooting
                fi
            fi
        else
            echo "No installed_cards file found.. creating now." >> $LOG
            while read line; do
                if [ "${line:0:9}" = "SUBSYSTEM" ]; then
                    mac=${line:50:17}
                    ifname=${line:107:4}

                    if ip link show | grep -q "$mac"; then
                        echo "Adding $ifname=$mac to installed_cards" >> $LOG
                        echo "SUBSYSTEM==\"net\", ACTION==\"add\", SYSFS{address}==\"$mac\", IMPORT=\"/lib/udev/rename_netiface %k $ifname\"" >> $new_persist_file
                        echo "$ifname=$mac" >> $new_installed_cards_file
                    else
                        echo "$mac does not appear to be installed anymore" >> $LOG
                    fi
                fi
            done < $persist_file

            mv -f $new_persist_file $persist_file
            mv -f $new_installed_cards_file $installed_cards_file

            echo "Done processing persistent names file" >> $LOG
        fi
    else
        echo "No persistent names file.. something is very wrong" >> $LOG
    fi
else
    echo "Couldn't find the network/data directory.. leaving persistent names file alone" >> $LOG
fi

# Create default configs for any new cards
for intf in $(ifconfig -a | grep "^eth[[:digit:]]" | cut -d' ' -f 1); do
    config_file="/etc/sysconfig/network/ifcfg-$intf"
    if [ -e "$config_file" ]; then
        echo "Config already exists for $intf" >> $LOG
    else
        echo "No config file found for $intf.. creating." >> $LOG
        write_default_config $config_file
    fi
done

for intf in $(ifconfig -a | grep "^tr[[:digit:]]" | cut -d' ' -f 1); do
    config_file="/etc/sysconfig/network/ifcfg-$intf"
    if [ -e "$config_file" ]; then
        echo "Config already exists for $intf" >> $LOG
    else
        echo "No config file found for $intf.. creating." >> $LOG
        write_default_config $config_file
    fi
done


# Create a symbolic link to modprobe.conf if it exists
if [ -e /etc/modprobe.conf ]; then
    if [ ! -e /etc/modules.conf ]; then
        echo "Creating symbolic link to modprobe.conf" >> $LOG
        ln -s /etc/modprobe.conf /etc/modules.conf >> $LOG 2>&1
    elif [ ! -L /etc/modules.conf ]; then
        echo "/etc/modules.conf was *not* a link.. deleting and creating link." >> $LOG
        rm -f /etc/modules.conf >> $LOG 2>&1
        ln -s /etc/modprobe.conf /etc/modules.conf >> $LOG 2>&1
    fi
fi

echo "Loading IPv6 module.." >> $LOG
modprobe ipv6 >> $LOG 2>&1

# try to disable default autoconf for ipv6
if [ -e /proc/sys/net/ipv6/conf/default/autoconf ]; then
    echo "Disabling autoconf in net/ipv6/conf/default." >> $LOG
    echo "0" > /proc/sys/net/ipv6/conf/default/autoconf
fi

# try to disable privacy extensiosn for ipv6
if [ -e /proc/sys/net/ipv6/conf/default/use_tempaddr ]; then
    echo "Disabling privacy extensions in net/ipv6/conf/default." >> $LOG
    echo "0" > /proc/sys/net/ipv6/conf/default/use_tempaddr
fi

