summaryrefslogblamecommitdiffstats
path: root/builder/modules.d/slx-network/scripts/udhcpc-trigger.stage4
blob: b4dfeafa0594fc640e0f8e1a3633efedb83d4d95 (plain) (tree)
1
2
3
4
5
6
7
8
9
           
 

                                                                    




                                                    
                                


                                                         
 




                                                                     
                                      
                                               































                                                                                                                    

                                                 
                                                  


                                               

 


                              































































                                                                                                                    
















                                                                                  
 














                                                                                                                                            














































                                                                                                                    
#!/bin/bash
#
# This script is triggered by udhcpc and handle the DHCP information
# given to this script as parameters.

export PATH=$PATH:/opt/openslx/sbin:/opt/openslx/bin

. /opt/openslx/config

if [ -z "$SLX_PXE_NETIF" ]; then
	echo "Missing PXE network interface information."
	exit 1
fi

MAIN_NETIF="$SLX_PXE_NETIF"
[ -n "$SLX_VLAN_ID" ] && MAIN_NETIF="${SLX_PXE_NETIF}.${SLX_VLAN_ID}"
[ -n "$SLX_BRIDGE" ]  && MAIN_NETIF="$SLX_BRIDGE"
readonly MAIN_NETIF

RESOLV_CONF="/opt/openslx/resolv.conf"
THIS_RESOLV="/run/network/${MAIN_NETIF}.resolv"

rebuild_resolv_conf () {
	# Don't do anything if the active resolv.conf is not ours
	# Also this will not run resolvconf update.d... No idea if we should still do so...
	[ -L "/etc/resolv.conf" ] || return 0
	[ "x$(readlink "/etc/resolv.conf")" == "x${RESOLV_CONF}" ] || return 0
	# Maybe make this smarter some time, if anyone is using clients that are on multiple networks at once etc...
	# This is a little braindead but should work most of the time
	sort -u /run/network/*.resolv > "$RESOLV_CONF" 2> /dev/null

	# add support for resolv.conf update scripts // see man(8) resolvconf
	for s in /etc/resolvconf/update.d/*.sh; do
		[ -f "$s" ] && [ -x "$s" ] && "$s"
	done
}

escape_search() {
	echo "$@" | sed -e 's/[]\/()$*.^|[]/\\&/g'
}

escape_replace() {
	echo "$@" | sed -e 's/[\/&]/\\&/g'
}

check_env() {
	if [ -z "$ip" ] || [ -z "$subnet" ] || [ -z "$interface" ]; then
		echo "$1 event with missing data" >&2
		echo "ip = '$ip'" >&2
		echo "subnet = '$subnet'" >&2
		echo "interface = '$interface'" >&2
		exit 1
	fi
	# only run for the boot network interface
	# TODO VLAN support
	if [ "$interface" != "$MAIN_NETIF" ]; then
		echo "Ignoring '$interface'..."
		exit 1
	fi
}

case "$1" in
	bound|renew)
		check_env "$1"
		# Set address on interface
		ip addr add "$ip/$(ipcalc -s -p "$ip" "$subnet" | sed s/.*=//)" dev "$interface"
		# Set default route, if given
		if [ -n "$router" ]; then
			ip route replace default via "$router"
		fi
		
		# get domain, hostname and thus fqdn from DNS
		dns_fqdn=$(busybox timeout -t 3 rdns "$ip")
		dns_short="${dns_fqdn%%.*}"
		# check if it is fqdn
		if [ "$dns_fqdn" == "$dns_short" ]; then
			unset dns_fqdn dns_short
		fi

		# Update resolver configuration file
		conf_file="$(mktemp)"
		# Own domain suffix
		if [ -n "$domain" ]; then
			:
		elif [ -n "$dns_fqdn" ]; then
			domain="${dns_fqdn#*.}"
			
		elif [ -n "$SLX_NET_DOMAIN" ]; then
			domain="$SLX_NET_DOMAIN"
		fi
		if [ -n "$domain" ]; then
			echo "domain ${domain%% *}" >> "${conf_file}"
		fi
		# Add domain to list of search domains if not in there yet
		if [ -n "$domain" ] && [ -n "$search" ]; then
			FOUND=no
			for sd in $search; do
				[ "x$sd" = "x$domain" ] && FOUND=yes
			done
			[ "$FOUND" = "no" ] && search="$domain $search"
		elif [ -n "$domain" ]; then
			search="$domain"
		fi
		# Search domains
		if [ -n "$search" ]; then
			echo "search $search" >> "${conf_file}"
		elif [ -n "$SLX_NET_SEARCH" ]; then
			echo "search $SLX_NET_SEARCH" >> "${conf_file}"
		elif [ -n "$SLX_NET_DOMAIN" ]; then
			echo "search $SLX_NET_DOMAIN" >> "${conf_file}"
		fi
		for i in $dns; do
			echo "$0: Adding DNS $i"
			echo "nameserver $i" >> "${conf_file}"
		done
		
		if [ -x "/sbin/resolvconf" ] && [ -L "/etc/resolv.conf" ] && [ -d "/etc/resolvconf/update.d" ]; then
			# Automatic handling :-)
			resolvconf --create-runtime-directories
			resolvconf --enable-updates
			< "$conf_file"  resolvconf -a "${interface}.udhcpc"
			rm -- "$conf_file"
		else
			# Manual handling required :-(
			mv -f "$conf_file" "$THIS_RESOLV"
			rebuild_resolv_conf
		fi

		# TODO: check if we really want/need to overwrite the PXE_IP,
		# it might be better/clearer to change the SLX_DHCP_CLIENT_IP...
		sed -i "s/^\(SLX_PXE_CLIENT_IP=\).*$/\1'$ip'/" /opt/openslx/config
		# Write DOMAIN and SEARCH to /opt/openslx/config if empty
		if [ -z "$SLX_NET_DOMAIN" ] && [ -n "$domain" ]; then
			sed -i "/^SLX_NET_DOMAIN=/d" /opt/openslx/config
			echo "SLX_NET_DOMAIN='$domain'" >> /opt/openslx/config
		fi
		if [ -z "$SLX_NET_SEARCH" ] && [ -n "$search" ]; then
			sed -i "/^SLX_NET_SEARCH=/d" /opt/openslx/config
			echo "SLX_NET_SEARCH='$search'" >> /opt/openslx/config
		fi
		# Same for WINS servers
		if [ -z "$SLX_NET_WINS" ] && [ -n "$wins" ]; then
			sed -i "/^SLX_NET_WINS=/d" /opt/openslx/config
			echo "SLX_NET_WINS='$wins'" >> /opt/openslx/config
		fi

		# TODO find a better way to trigger additional code, hook dir?
		# Update /etc/issue for proper spacing
		[ -x "/opt/openslx/scripts/openslx-create_issue" ] && /opt/openslx/scripts/openslx-create_issue

		# Remove any stray addresses; we expect the primary interface to only have one
		# address supplied via DHCP. We do this after adding the new one, obviously.
		rem_list=$( ip -o addr show "$interface" | awk '{ for (i=1;i<NF;++i) if ($i == "inet") print $(i+1) }' | grep -v "^${ip}/" )
		if [ -n "$rem_list" ]; then
			echo "PRIMARY: Removing $rem_list since we just got assigned $ip"
			echo 1 > "/proc/sys/net/ipv4/conf/$interface/promote_secondaries"
			for addr in $rem_list; do
				ip addr del "$addr" dev "$interface"
				sed -i "/^$(escape_search "${addr%/*}")(\s|$)/d" /etc/hosts
			done
		fi
		
		# Write to openslx-config
		echo "# Config written by openslx-dhcp-script (2)" >> /opt/openslx/config
		sed -i "/^SLX_DNS=/d" /opt/openslx/config
		echo "SLX_DNS='$dns'" >> /opt/openslx/config
	;;
	
	deconfig)
		check_env "$1"
		if [ "$interface" = "$primary" ]; then
			echo "Ignoring deconfig for primary interface"
		else
			echo 1 > "/proc/sys/net/ipv4/conf/$interface/promote_secondaries"
			clientip=${ip%%:*}
			ip addr del "$clientip/$(ipcalc -s -p "$clientip" "$subnet" | sed s/.*=//)" dev "$interface"
			sed -i "/^$(escape_search "$ip")(\s|$)/d" /etc/hosts
		fi
		
		if [ -x /sbin/resolvconf ] && [ -L /etc/resolv.conf ] && [ -d /etc/resolvconf/update.d ]; then
			# Automatic handling :-)
			resolvconf -d "${interface}.udhcpc"
		else
			# Manual handling required :-(
			rm -f -- "$THIS_RESOLV"
			rebuild_resolv_conf
		fi
	;;
	
	leasefail)
		echo "$0: Lease failed: $message" >&2
		
	;;
	
	nak)
		echo "$0: Received a NAK: $message" >&2
		
	;;
	
	*)
		echo "$0: Unknown udhcpc command: $1" >&2
		exit 1
		
	;;
esac

exit 0