summaryrefslogblamecommitdiffstats
path: root/modules.d/slx-network/hooks/s3-setup-bootif-network.sh
blob: 1ae584648743ec9330ce21e3162bc40e04b7f1c0 (plain) (tree)
1
2
3
4
5
6
7
           





                                                                




                                                            









                                                                                  
 



                                                            
                                                                      
                       
                               


         


                                 

                      




                                                 







                                                                                                                        


                             
                                                  
                                                                                
            
                                   





                                                                             






                                   
                                             

                                                                           

  














                                                                                  
                             
                                 
                    




                                                             
                                                       

                                                
                       


                                                

                              
                                      
                                                                                         
                              



                                                                                    


                             
 











                                                                               
                                                      




                                                                                                
  
 
       

                                                                
                  

                                                                                      
                                                                  



                                                                                                                        
                                                   



                                    
                                                    

  

                              
                          





                                

                       



                                                                         
                                   
                                    

                                         



                                                    



                
                                                          
#!/bin/bash
#
# This script sets up the main network interface we booted from,
# as designated by SLX_PXE_NETIF (parsed from the PXE KCL in the
# cmdline dracut hook).
# It is run inside dracut's initqueue, on settles to detect the
# physical network interface as fast as possible.

type emergency_shell >/dev/null 2>&1 || . /lib/dracut-lib.sh

. /run/openslx/network.conf

# do not run until the physical interface exists (driver loaded)
_fails=0
while ! [ -e "/sys/class/net/${SLX_PXE_NETIF}/device" ]; do
	if (( ++_fails > 20 )); then
		emergency_shell "Boot interface '${SLX_PXE_NETIF}' did not appear"
		exit 1
	fi
	(( (_fails % 5) == 0 )) && udevadm trigger
	usleep 500000
done

# wrapper around splashtool to disable it if its not present
_splashtool() {
	:
}
if grep -wq splash /proc/cmdline && hash splashtool &> /dev/null; then
	_splashtool() {
		splashtool "$@"
	}
fi

wait_for_iface() {
	local _iface="$1"
	local _timeout="${2:-50}"
	local _fails=0
	local _state
	if [ "$_iface" = "$SLX_PXE_NETIF" ]; then
		img="??-nic"
	elif [ "$_iface" = "$SLX_BRIDGE" ]; then
		img="??-bridge"
	fi
	while (( _timeout-- > 0 )); do
		_state="$(cat "/sys/class/net/${_iface}/operstate" 2> /dev/null)"
		[ "$_state" = "up" ] && break
		if (( ++_fails > 5 )) && [[ "$_state" = "unknown" || "$_state" = "" ]]; then
			if (( _fails > 10 )) || [ "$(cat "/sys/class/net/${_iface}/carrier" 2> /dev/null)" = "1" ]; then
				break
			fi
		fi
		# every 500ms
		usleep 500000
		in=
		(( (_timeout % 2) == 0 )) && in=in
		_splashtool --icon "/opt/openslx/icons/${in}active/${img}.ppm" &
	done
	if (( _timeout > 0 )); then
		_splashtool --icon "/opt/openslx/icons/active/${img}.ppm" &
		return 0
	else
		_splashtool --icon "/opt/openslx/icons/inactive/${img}.ppm" &
		return 1
	fi
}

# For debugging...
{
set -x

ip link set dev "$SLX_PXE_NETIF" up
if ! wait_for_iface "$SLX_PXE_NETIF" 60; then
	warn "'$SLX_PXE_NETIF' still not up after 30sec ... trying anyway."
	# TODO handle case where we waited for 30sec and it is still not up
fi

# now determine whether we are in bridged/vlan/plain mode
MAIN_NETIF="$SLX_PXE_NETIF"
if [ -n "$SLX_VLAN_ID" ]; then
	# create VLAN interface
	modprobe 8021q || warn "Loading '8021q' failed - missing module?"
	ip link add link "$SLX_PXE_NETIF" name "${SLX_PXE_NETIF}.${SLX_VLAN_ID}" \
		type vlan id "$SLX_VLAN_ID"
	ip link set dev "${SLX_PXE_NETIF}.${SLX_VLAN_ID}" up
	if wait_for_iface "${SLX_PXE_NETIF}.${SLX_VLAN_ID}"; then
		MAIN_NETIF="${SLX_PXE_NETIF}.${SLX_VLAN_ID}"
	else
		warn "Setting up VLAN '$SLX_VLAN_ID' failed, trying plain..."
	fi
fi

if [ -n "$SLX_BRIDGE" ]; then
	for try in {1..10} ""; do
		if (
		set -e
		brctl addbr "$SLX_BRIDGE"
		brctl stp "$SLX_BRIDGE" 0
		brctl setfd "$SLX_BRIDGE" 0.000000000001
		ip link set addr "$SLX_PXE_MAC" "$SLX_BRIDGE"
		brctl addif "$SLX_BRIDGE" "$MAIN_NETIF"
		ip link set dev "$SLX_BRIDGE" up
		wait_for_iface "$SLX_BRIDGE"
		); then
			MAIN_NETIF="$SLX_BRIDGE"
			break
		fi

		# nope, handle
		if [ -z "$try" ]; then
			emergency_shell "Failed to setup main network bridge, giving up!"
			exit 1
		fi
		warn "Failed to setup main network bridge on try $try. Retrying ..."
		# delete bridge, inc try and sleep 100ms before trying again
		[ -e "/sys/class/net/${SLX_BRIDGE}" ] && brctl delbr "$SLX_BRIDGE"
		usleep 100000
	done
fi

# Finally add the IP address on the main NIC.
# Note: we should never have ip & netmask without the other.
if [ -n "$SLX_PXE_CLIENT_IP" ] && [ -n "$SLX_PXE_NETMASK" ]; then
	ip addr add "${SLX_PXE_CLIENT_IP}/${SLX_PXE_NETMASK}" dev "$MAIN_NETIF"

	# now if we got everything from the KCL and skip dhcp if so
	if [ -n "$SLX_PXE_GATEWAY" ] && [ -n "$SLX_PXE_DNS" ]; then
		info "Got network configuration from KCL, skipping DHCP."
		if ! interface="$MAIN_NETIF" \
			ip="$SLX_PXE_CLIENT_IP" \
			router="$SLX_PXE_GATEWAY" \
			dns="$SLX_PXE_DNS" \
			hostname="$SLX_PXE_HOSTNAME" \
			/usr/local/bin/udhcpc-trigger bound; then
			warn "Failed to launch DHCP trigger with KCL configuration - will DHCP."
		fi
		exit 0
	fi
fi

## DHCP
# Try to work around some buggy e1000e variants by waiting a bit
sleep 1
additional_opts=()

# we need to send the same UID (without '-') as the PXE firmware did, so use the plain
# one read with dmidecode (and not the one by s3-get-system-uuid).
if [ "$USE_DHCP_UUID" = "yes" ]; then
	UID="$(dmidecode -s system-uuid | sed -r 's/^(..)(..)(..)(..)-(..)(..)-(..)(..)-(....)-/00\4\3\2\1\6\5\8\7\9/')"
	if [ "${#UID}" = 34 ]; then
		echo "Using SMBIOS UID for DHCP"
		additional_opts+=("-x" "0x3d:$UID")
	fi
fi

if [ -n "$SLX_PXE_CLIENT_IP" ]; then
	additional_opts+=("-r" "$SLX_PXE_CLIENT_IP")
fi

# DHCP options to request
request_opts=("-O" "hostname")
request_opts+=("-O" "dns")
request_opts+=("-O" "ntpsrv")
request_opts+=("-O" "domain")
request_opts+=("-O" "wpad")
request_opts+=("-O" "search")
request_opts+=("-O" "nisdomain")

# udhcpc
for i in 1 1 1 fail; do
	if [ "$i" = "fail" ]; then
		emergency_shell "DHCP failed 3 times... cannot continue."
		exit 1
	fi
	udhcpc -t 4 -T 3 -f -n -q \
		-i "${MAIN_NETIF}" \
		"${request_opts[@]}" \
		"${additional_opts[@]}" \
		-s "/usr/local/bin/udhcpc-trigger" \
		&& break
	# failed, keep trying...
	warn "DHCP failed, retrying in $i sec..."
	sleep $i
done

set +x
} {BASH_XTRACEFD}> "/run/openslx/initramfs-network.log.$$"