diff options
Diffstat (limited to 'modules.d/slx-network/scripts/udhcpc-trigger.stage4')
-rwxr-xr-x | modules.d/slx-network/scripts/udhcpc-trigger.stage4 | 208 |
1 files changed, 208 insertions, 0 deletions
diff --git a/modules.d/slx-network/scripts/udhcpc-trigger.stage4 b/modules.d/slx-network/scripts/udhcpc-trigger.stage4 new file mode 100755 index 00000000..b4dfeafa --- /dev/null +++ b/modules.d/slx-network/scripts/udhcpc-trigger.stage4 @@ -0,0 +1,208 @@ +#!/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 + |