Fix quick-register broadcast detection on Proxmox bridges
CI / Lint + build + test (push) Failing after 5m17s

Two bugs compounded on Proxmox hosts: primary_iface walked
`ip link show` and picked the physical NIC (e.g. enp1s0), which has
no IPv4 on Proxmox because the address lives on vmbr0. Even if vmbr0
had been picked, the kernel reports its broadcast as 0.0.0.0, so the
script fell all the way back to 255.255.255.255.

Now we prefer the default-route interface (vmbr0 on Proxmox, eno1 on
bare metal) and, when `ip` doesn't surface a usable `brd`, compute
the broadcast from the inet CIDR instead of giving up.
This commit is contained in:
2026-04-17 22:57:49 -04:00
parent 8b3d9a312e
commit d24207427f
+41 -8
View File
@@ -26,16 +26,40 @@ if [[ -z "${ORCH_URL}" ]]; then
fi fi
primary_iface() { primary_iface() {
# Pick the first physical ethernet-style interface that isn't a loopback, # Prefer the interface carrying the default route — that's the
# bridge, veth, docker, virbr, bond, tun, or tap. # canonical "primary" iface (e.g. vmbr0 on Proxmox, eno1 on bare
ip -o link show 2>/dev/null \ # metal). `ip link show` order picks the physical NIC on Proxmox,
| awk '$0 ~ /link\/ether/ { # but that NIC has no IPv4, so we'd miss the broadcast address.
name=$2; sub(":","",name) local iface
if (name ~ /^(lo|docker|br-|veth|virbr|bond|tun|tap|wlan|wlp)/) next iface="$(ip -o -4 route show default 2>/dev/null \
| awk '{for(i=1;i<=NF;i++) if($i=="dev") {print $(i+1); exit}}')"
if [[ -n "${iface}" ]]; then
echo "${iface}"
return
fi
# Fallback: first non-virtual interface that has an IPv4 address.
ip -o -4 addr show 2>/dev/null \
| awk '{
name=$2
if (name ~ /^(lo|docker|br-|veth|virbr|bond|tun|tap|fwbr|fwpr|fwln|wlan|wlp)/) next
print name; exit print name; exit
}' }'
} }
# compute_broadcast "192.168.1.250/24" → "192.168.1.255"
compute_broadcast() {
local cidr="$1" ip prefix a b c d host mask inv bc
ip="${cidr%/*}"
prefix="${cidr#*/}"
[[ "${ip}" == *.*.*.* && "${prefix}" =~ ^[0-9]+$ ]] || return 1
IFS=. read -r a b c d <<<"${ip}"
host=$(( (a<<24) | (b<<16) | (c<<8) | d ))
mask=$(( (0xFFFFFFFF << (32 - prefix)) & 0xFFFFFFFF ))
inv=$(( (~mask) & 0xFFFFFFFF ))
bc=$(( host | inv ))
printf '%d.%d.%d.%d' $(( (bc>>24)&0xFF )) $(( (bc>>16)&0xFF )) $(( (bc>>8)&0xFF )) $(( bc&0xFF ))
}
IFACE="$(primary_iface || true)" IFACE="$(primary_iface || true)"
if [[ -z "${IFACE}" ]]; then if [[ -z "${IFACE}" ]]; then
echo "ERROR: could not pick a primary network interface." >&2 echo "ERROR: could not pick a primary network interface." >&2
@@ -50,8 +74,17 @@ if [[ -z "${MAC}" ]]; then
fi fi
if [[ -z "${WOL_BROADCAST:-}" ]]; then if [[ -z "${WOL_BROADCAST:-}" ]]; then
WOL_BROADCAST="$(ip -o -4 addr show dev "${IFACE}" 2>/dev/null \ ipinfo="$(ip -o -4 addr show dev "${IFACE}" 2>/dev/null || true)"
| awk '{for(i=1;i<=NF;i++) if($i=="brd") {print $(i+1); exit}}')" WOL_BROADCAST="$(awk '{for(i=1;i<=NF;i++) if($i=="brd") {print $(i+1); exit}}' <<<"${ipinfo}")"
# Bridges (vmbr0 on Proxmox, br0 on Linux bridges) often report
# brd 0.0.0.0 or omit it entirely. Compute from the inet CIDR
# before giving up on 255.255.255.255.
if [[ -z "${WOL_BROADCAST}" || "${WOL_BROADCAST}" == "0.0.0.0" ]]; then
cidr="$(awk '{for(i=1;i<=NF;i++) if($i=="inet") {print $(i+1); exit}}' <<<"${ipinfo}")"
if [[ "${cidr}" == */* ]]; then
WOL_BROADCAST="$(compute_broadcast "${cidr}" || true)"
fi
fi
fi fi
WOL_BROADCAST="${WOL_BROADCAST:-255.255.255.255}" WOL_BROADCAST="${WOL_BROADCAST:-255.255.255.255}"
WOL_PORT="${WOL_PORT:-9}" WOL_PORT="${WOL_PORT:-9}"