diff --git a/postinstall/init.sh b/postinstall/init.sh index 16ba387..abdd032 100644 --- a/postinstall/init.sh +++ b/postinstall/init.sh @@ -1,12 +1,47 @@ #!/usr/bin/env bash -# Get the current DHCP network address, gateway and DNS servers -NIC=$(ip link | grep "^2:" | awk '{print $2}' | tr -d ":") -IP_ADDRESS=$(ip address show ${NIC} | grep -E "inet " | awk '{print $2}') -NETMASK=$(echo ${IP_ADDRESS} | sed 's/.*\///') -IP_ADDRESS=$(echo ${IP_ADDRESS} | sed 's/\/.*//') -GATEWAY=$(ip route | grep "default" | awk '{print $3}') -DNS_SERVERS=$(awk '/^nameserver/ {print $2}' /etc/resolv.conf | xargs) +# Get the current DHCP network address, gateway and DNS servers. DHCP can +# still be completing when this service starts, even after network-online. +get_network_settings() { + local cidr_address + + # Clear every value before each attempt so a partial/stale DHCP lease can + # never be written to the static network configuration. + NIC="" + IP_ADDRESS="" + NETMASK="" + GATEWAY="" + DNS_SERVERS="" + + NIC=$(ip link | awk -F ': ' '$1 == 2 {sub(/@.*/, "", $2); print $2; exit}') + [ -n "${NIC}" ] || return 1 + + cidr_address=$(ip -4 address show "${NIC}" | awk '/inet / {print $2; exit}') + [ -n "${cidr_address}" ] || return 1 + + IP_ADDRESS=${cidr_address%/*} + NETMASK=${cidr_address#*/} + GATEWAY=$(ip route show default | awk 'NR == 1 {print $3}') + DNS_SERVERS=$(awk '/^nameserver/ {print $2}' /etc/resolv.conf | xargs) + + [ -n "${IP_ADDRESS}" ] && [ -n "${NETMASK}" ] && \ + [ -n "${GATEWAY}" ] && [ -n "${DNS_SERVERS}" ] +} + +MAX_NETWORK_ATTEMPTS=10 +for attempt in $(seq 1 "${MAX_NETWORK_ATTEMPTS}"); do + if get_network_settings; then + break + fi + + if [ "${attempt}" -eq "${MAX_NETWORK_ATTEMPTS}" ]; then + echo "DHCP network settings were incomplete after ${MAX_NETWORK_ATTEMPTS} attempts; aborting postinstall." >&2 + exit 1 + fi + + echo "DHCP network settings are not ready (attempt ${attempt}/${MAX_NETWORK_ATTEMPTS}); retrying in 3 seconds." >&2 + sleep 3 +done # Tear down DHCP first, while interfaces is still dhcp, so dhcpcd is gone # before we write a static resolv.conf (otherwise it rewrites it on exit)