#!/bin/bash # # This script is triggered by udhcpc in stage3 and handle the # DHCP information given as parameters { # for debugging set -x NETWORK_CONF="/run/openslx/network.conf" . "$NETWORK_CONF" 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 if [[ "$1" != "bound" && "$1" != "renew" ]] \ || [ "$interface" != "${MAIN_NETIF}" ] \ || [ -z "$ip" ]; then exit 0 fi log() { echo "${MAIN_NETIF}: $*" } ## ## CORE NETWORK CONFIGURATION ## ## > IP, subnet, route # If we already got an IP from KCL, see if it differs, and remove first if so # We just try to prevent everything from breaking if the DHCP server doesn't # objey the renew request by the client and hands out a new address if [ -n "$SLX_PXE_CLIENT_IP" ]; then #...some address is already configured... if [ "${SLX_PXE_CLIENT_IP}" != "${ip}" ]; then #...it's a different one, reconfigure... log "reconfiguring from '${SLX_PXE_CLIENT_IP}' to '${ip}'" # remove default route and let it be added again below, as it might get lost when changing the primary address on the interface ip route del default ip addr del "$SLX_PXE_CLIENT_IP" dev "${interface}" fi else #...no address configured yet, just add... log "adding ${ip}" fi if ! ip addr show dev "${interface}" | grep -qF "inet ${ip}/"; then ip addr add "${ip}/$(ipcalc -s -p "${ip}" "${subnet}" | sed s/.*=//)" dev "${interface}" echo "SLX_DHCP_CLIENT_IP='$ip'" >> "$NETWORK_CONF" fi # Same procedure for default gateway if [ -n "$router" ]; then if [ -n "$SLX_PXE_GATEWAY" ] && [ "$SLX_PXE_GATEWAY" != "$router" ]; then log "reconfiguring default gw from '$SLX_PXE_GATEWAY' to '$router'" ip route del default fi ip route add default via "$router" dev "${MAIN_NETIF}" echo "SLX_DHCP_GATEWAY='$router'" >> "$NETWORK_CONF" fi ## ## ADDITIONAL NETWORK CONFIGURATION ## ## > DNS, domain, hostname rm -f -- "/etc/resolv.conf" reverse_lookup() { [ -z "$dns" ] && return [ -z "$1" ] && return timeout 3 nslookup "$1" | awk '{ if ($2 == "name") { print gensub("\\.$", "", 1, $4); exit; } if ($1 == "Name:") { ok = 1 } if (ok && $1 == "Address") { print gensub("\\.$", "", 1, $4); exit; } }' } echo "# From DHCP in stage 3.1" >> "$NETWORK_CONF" # DNS/domain? if [ -n "$dns" ]; then log "DNS servers: $dns" echo "SLX_DNS='$dns'" >> "$NETWORK_CONF" for srv in $dns; do echo "nameserver $srv" >> "/etc/resolv.conf" done else dns="$( < /etc/resolv.conf awk '$1 == "nameserver" {printf "%s ", $2}' )" fi # always check DNS log "checking reverse DNS record for this host" [ -n "$fqdn" ] && [[ "$fqdn" != *.* ]] && fqdn= [ -z "$fqdn" ] && fqdn="$( reverse_lookup "$ip" )" [ -z "$fqdn" ] && [ -n "$hostname" ] && [ -n "$domain" ] && fqdn="${hostname}.${domain}" # retry DNS one time if [ -z "$fqdn" ]; then log "found no way to generate FQDN, trying reverse lookup one more time" sleep 1 fqdn="$( reverse_lookup "$ip" )" fi if [ -n "$fqdn" ]; then fqdn_hostname="${fqdn%%.*}" fqdn_domain="${fqdn#*.}" fi if [ -z "$hostname" ] && [ -n "$fqdn_hostname" ]; then hostname="${fqdn_hostname}" log "using hostname from DNS, as DHCP didn't supply one" fi if [ -z "$hostname" ] && [ -n "$SLX_PXE_HOSTNAME" ]; then hostname="$SLX_PXE_HOSTNAME" log "using hostname from KCL, as DHCP/DNS didn't supply one" fi if [ -z "$hostname" ]; then hostname="noname-${ip//./-}" log "got no hostname via DHCP, DNS or KCL, using fallback '$hostname'" fi if [ -z "$domain" ] && [ -n "$fqdn_domain" ]; then domain="${fqdn_domain}" log "using domain from DNS, as DHCP didn't supply one" fi domain="${domain%% *}" # in case domain is a list, some DHCP servers did that in the past instead of using search # Normalize to lowercase for var in hostname domain fqdn search fqdn_hostname fqdn_domain SLX_PXE_HOSTNAME; do declare "$var"="${!var,,}" done # 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 [ "$sd" = "$domain" ] && FOUND=yes done [ "$FOUND" = "no" ] && search="$domain $search" elif [ -n "$domain" ]; then search="$domain" fi # Write out if [ -n "$domain" ]; then echo "domain $domain" >> "/etc/resolv.conf" echo "SLX_NET_DOMAIN='$domain'" >> "$NETWORK_CONF" fi if [ -n "$search" ]; then echo "search $search" >> "/etc/resolv.conf" echo "SLX_NET_SEARCH='$search'" >> "$NETWORK_CONF" fi if [ -n "$ntpsrv" ]; then echo "SLX_DHCP_NTP='$ntpsrv'" >> "$NETWORK_CONF" fi declare -a localnames=() [ -n "$fqdn" ] && localnames+=( "$fqdn" ) [ -n "$hostname" ] && localnames+=( "$hostname" ) [ -n "$fqdn_hostname" ] && [ "$hostname" != "$fqdn_hostname" ] && localnames+=( "$fqdn_hostname" ) [ -n "$SLX_PXE_HOSTNAME" ] && [ "$hostname" != "$SLX_PXE_HOSTNAME" ] && localnames+=( "$SLX_PXE_HOSTNAME" ) { echo "127.0.0.1 localhost" echo "127.0.1.1 ${localnames[*]}" } > "/etc/hosts" log "setting hostname $hostname, FQDN $fqdn" echo "$hostname" > "/proc/sys/kernel/hostname" echo "$hostname" > "/etc/hostname" echo "SLX_HOSTNAME='$hostname'" >> "$NETWORK_CONF" touch /.network set +x } {BASH_XTRACEFD}> "/run/openslx/initramfs-udhcpc.log.$$"