#!/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 "/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