summaryrefslogblamecommitdiffstats
path: root/core/modules/dhcpc-busybox/data/opt/openslx/scripts/udhcpc-openslx
blob: 05a08b8fca4edbe11bfd495f3de0e9fb7bf6239f (plain) (tree)
1
2
3
4
5
6
7
8
9



                                                                               
                                                 
 

                                                                         
 
                                                                   
                                              

                                                                            
 





                                                                               


                                                        

                     
                                        
 

                                                          
                                                 
 















                                                                          

                



                                                                                           
                                                                              

                                                                           
                                                                          



                                                                               
                                                                              
                         







                                                              

                                        


















                                                                                        
                                             

                                                                             


                                                  


                 
                                              


                  
                                      


             
                                                                        







                                                     

                       




                                          
                                                                                                    

                                             




                                                                                                                          
                  
 
                                                             
                                                        






                                                        
                                     
                                   
                                         
                         

                                               
 

                                                   
                  
                                         
                                                                     











                                                                          
                                         
                                                               
                                                   
                                                                       
                                                   
                                                                       


                                                
                                                              

                    


                                                 


                                                                                                 
                                                      

                                                                                          

                                                                                 


                                                                                      

                                                                                      

                                                                         

                                                                                  
 

                                                                          
                                                 
















                                                                                                     




                                                                                       
                                                                       

                                                                                                                         

                                                                                                                    


                                          

                                                                         
                                             






                                                                                                                     











                                                                                                                                                    




                                                          
                                                                                                                                                    















                                                                                                                                     
                                                           


                                                                                                 
                  


                                                                                      



                              


                                                                      

                                                                                         
                                                                                                                    
                                                                            

                  


                                              




















                                                         
#!/bin/bash
# Needs bash for printf -v VARNAME
# -----------------------------------------------------------------------------
#
# Copyright (c) 2011..2018 bwLehrpool-Projektteam
#
# This program/file is free software distributed under the GPL version 2.
# See https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
#
# If you have any feedback please consult https://bwlehrpool.de and
# send your feedback to support@bwlehrpool.de.
#
# General information about bwLehrpool can be found at https://bwlehrpool.de
#
# -----------------------------------------------------------------------------
#
#                               Mini-Linux Toolkit
#
# -----------------------------------------------------------------------------

# DO NOT RENAME/MOVE THIS FILE!
# The slx-network dracut module checks for its existence

. /opt/openslx/config

declare -rg primary="${SLX_BRIDGE:-br0}"

declare -rg RESOLV_CONF="/opt/openslx/resolv.conf"
declare -rg THIS_RESOLV="/run/network/${interface}.resolv"
declare -rg flag="/run/network/primary-dhcp.flag"

if [ "$1" = "--lock-hostname-updates" ]; then
	# If we change the hostname while Xorg is running, this might
	# cause issues, depending on how it's set up. So we run this
	# script with the lock argument to touch the flag file right
	# before we try to launch lightdm/Xorg. In case the DHCP request
	# is too slow, this means we'll run with the wrong hostname
	# (potentially), but that's better than delaying the bootup
	# unnecessarily.
	# So also note that if you ever change this script's name/location
	# (JUST DON'T), you'd need to update all call sites, i.e. the
	# udhcpc startup script, and the lightdm service drop-in.
	mkdir -p /run/network
	touch "$flag"
	exit 0
fi

shopt -s extglob

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
	[ "$(readlink -f "/etc/resolv.conf")" = "${RESOLV_CONF}" ] || return 0
	# Fake file to merge in search domains from /opt/openslx/config
	echo "search $SLX_NET_SEARCH" > "/run/network/zzzzz-openslx.resolv"
	# Use extglob trickery to make sure br0/$primary stuff comes first
	# Then print them in a first-come-first-served manner.
	# Print nameserver entries one per line, print only first domain value,
	# group everything else together into one line.
	# Skip domain entirely if any search lines are found.
	cat "/run/network/$primary.resolv" /run/network/!("$primary").resolv \
		| gawk '{
			if ( $1 ~ /^[a-z]+$/ ) {
				for (i = 2; i <= NF; ++i) {
					if (done[$1][$i])
						continue
					done[$1][$i] = 1
					output[$1][++idx] = $i
				}
			} else {
				print $0
			}
		}
		END {
			for (s in output) {
				if (s == "nameserver") {
					for (t in output[s]) {
						print s " " output[s][t]
					}
				} else if (s == "domain" && isarray(output["search"])) {
				} else {
					printf "%s", s
					for (t in output[s]) {
						printf " %s", output[s][t]
						if (s == "domain")
							break
					}
					print ""
				}
			}
		}' \
		> "$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() {
	sed -e 's/[]\/()$*.^|[]/\\&/g' <<<"$@"
}

escape_replace() {
	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
}

mkdir -p "/run/network"

case "$1" in
	bound|renew)
		check_env "$1"
		mkdir -p "/run/dhcpc"
		# 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
			# Only replace route if it's the same interface as the current default route, or we don't have any
			current="$( ip route show | awk '{ if ($1 == "default") {print $5; exit 0}}' )"
			if [ -z "$current" ] || [ "$interface" = "$current" ]; then
				ip route replace default via "$router"
			fi
		fi

		# get domain, hostname and thus fqdn from DNS
		dns_fqdn=$(busybox timeout 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
		
		# Manual handling required :-(
		mv -f "$conf_file" "$THIS_RESOLV"
		rebuild_resolv_conf

		
		# Things that should only happen for the main interface that was used for booting
		if [ "$interface" = "$primary" ]; then
			# Update 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
				echo "SLX_NET_DOMAIN='$domain'" >> /opt/openslx/config
			fi
			if [ -z "$SLX_NET_SEARCH" ] && [ -n "$search" ]; then
				echo "SLX_NET_SEARCH='$search'" >> /opt/openslx/config
			fi
			# Same for WINS servers
			if [ -z "$SLX_NET_WINS" ] && [ -n "$wins" ]; then
				echo "SLX_NET_WINS='$wins'" >> /opt/openslx/config
			fi

			# Only update hostname if network is not ready yet
			# later on this might cause issues
			if ! [ -e "$flag" ]; then
				# Fallback for hostname
				if [ -z "$dns_fqdn" ] && [ -n "$domain" ] && [ -n "$hostname" ]; then
					# fallback to what the dhcp told us
					dns_fqdn="${hostname}.${domain}"
				fi
				if [ -z "$dns_fqdn" ]; then
					# Try currently set fqdn
					dns_fqdn="$( hostname -f )"
				fi
				if [ -z "$dns_fqdn" ]; then
					if [ -s "/etc/hostname" ]; then
						dns_fqdn="$( head -n 1 /etc/hostname )"
					else
						# Final fallback, nothing valid found
						dns_fqdn="noname-${ip//./-}.invalid"
					fi
				fi
				# finally, if dns_fqdn was set to anything, apply it
				if [ -n "$dns_fqdn" ]; then
					dns_short="${dns_fqdn%%.*}"
					echo "$dns_short" > "/proc/sys/kernel/hostname"
					echo "$dns_short" > "/etc/hostname"
					if [ -z "$SLX_HOSTNAME" ]; then
						echo "# Config written by openslx-dhcp-script (1)" >> /opt/openslx/config
						echo "SLX_HOSTNAME='$dns_short'" >> /opt/openslx/config
					elif [ "$SLX_HOSTNAME" != "$dns_short" ]; then
						sed -i "s/^\(SLX_HOSTNAME=\).*$/\1'$dns_short'/" /opt/openslx/config
					fi
				fi

				# Update /etc/issue for proper spacing
				/opt/openslx/scripts/openslx-create_issue
				touch "$flag"
				# end "network not ready yet"
			else
				# Network already going, make sure we don't change the primary hostname in /etc/hosts
				hostname=
				domain=
				dns_fqdn=
			fi
			# 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
		fi # end "primary only"
		
		# Hostname in /etc/hosts
		touch "/etc/hosts"
		hostlist=""
		[ -n "$dns_fqdn" ] && hostlist="$dns_fqdn"
		[ -n "$hostname" ] && [ -n "$domain" ] && [ "x${hostname}.${domain}" != "x$dns_fqdn" ] && hostlist="$hostlist ${hostname}.${domain}"
		if [ -n "$hostlist" ]; then
			for host in $hostlist; do
				host_short="${host%%.*}"
				[ "x$host_short" = "x$host" ] && host_short=""
				sed -i -r "s/\s$(escape_search "$host")(\s|$)/ /g" /etc/hosts
				[ -n "$host_short" ] && sed -i -r "s/\s$(escape_search "$host_short")(\s|$)/ /g" /etc/hosts
				if grep -q -E "^$ip\s" /etc/hosts; then
					sed -i "s/^$(escape_search "$ip")\s.*/$(escape_replace "$ip $host $host_short")/g" /etc/hosts
				else
					echo "$ip $host $host_short" >> /etc/hosts
				fi
			done
		fi
		# Get rid of orphaned lines in /etc/hosts
		sed -i -r '/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\s*$/d' /etc/hosts
		
		if [ -n "$dns" ] && [ -z "$SLX_DNS" ]; then
			# Write to openslx-config
			echo "# Config written by openslx-dhcp-script (2)" >> /opt/openslx/config
			echo "SLX_DNS='$dns'" >> /opt/openslx/config
		fi

		# Rewrite nat1 dhcpd config for VMs, and restart dnsmasq if it changed
		/opt/openslx/scripts/runvirt-start_dhcpd
	;;
	
	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
		
		# Manual handling required :-(
		rm -f -- "$THIS_RESOLV"
		rebuild_resolv_conf
	;;
	
	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