diff --git a/internal/web/register/quick.sh.tmpl b/internal/web/register/quick.sh.tmpl index 94f74d2..b4e21d8 100644 --- a/internal/web/register/quick.sh.tmpl +++ b/internal/web/register/quick.sh.tmpl @@ -26,16 +26,40 @@ if [[ -z "${ORCH_URL}" ]]; then fi primary_iface() { - # Pick the first physical ethernet-style interface that isn't a loopback, - # bridge, veth, docker, virbr, bond, tun, or tap. - ip -o link show 2>/dev/null \ - | awk '$0 ~ /link\/ether/ { - name=$2; sub(":","",name) - if (name ~ /^(lo|docker|br-|veth|virbr|bond|tun|tap|wlan|wlp)/) next + # Prefer the interface carrying the default route — that's the + # canonical "primary" iface (e.g. vmbr0 on Proxmox, eno1 on bare + # metal). `ip link show` order picks the physical NIC on Proxmox, + # but that NIC has no IPv4, so we'd miss the broadcast address. + local iface + 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 }' } +# 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)" if [[ -z "${IFACE}" ]]; then echo "ERROR: could not pick a primary network interface." >&2 @@ -50,8 +74,17 @@ if [[ -z "${MAC}" ]]; then fi if [[ -z "${WOL_BROADCAST:-}" ]]; then - WOL_BROADCAST="$(ip -o -4 addr show dev "${IFACE}" 2>/dev/null \ - | awk '{for(i=1;i<=NF;i++) if($i=="brd") {print $(i+1); exit}}')" + ipinfo="$(ip -o -4 addr show dev "${IFACE}" 2>/dev/null || true)" + 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 WOL_BROADCAST="${WOL_BROADCAST:-255.255.255.255}" WOL_PORT="${WOL_PORT:-9}"