A PC whose imaging failed and is re-imaged gets the same IP, and the
server still held state from the dead run, so net use failed (System
error 53). The April fix (18537ac) did not cover it:
- The dnsmasq hook only acted on 'add'/'del'. A re-image comes back to the
existing lease, which dnsmasq reports as 'old', and only when the
hostname/MAC changed. Now dnsmasq sets script-on-renewal, and the hook
clears state on 'old' when the request comes from PXE firmware or iPXE
(vendor class PXEClient), i.e. the machine just network-booted. A
Windows lease renewal (MSFT 5.0) is left alone.
- The 1 h conntrack timeout never applied after a reboot: systemd-sysctl
runs before ufw loads nf_conntrack, so the keys did not exist and the
5-day default stayed. /etc/modules-load.d/pxe-conntrack.conf loads it
first.
- smb-soft-reset.sh flushed neighbours on br-pxe, which no longer exists.
Live 2026-10-14. Hook tested on the server with an unused IP: network-boot
renewal clears, Windows renewal and no vendor class do not, add clears.
56 lines
1.7 KiB
Bash
Executable File
56 lines
1.7 KiB
Bash
Executable File
#!/bin/bash
|
|
#
|
|
# pxe-dhcp-hook.sh - dnsmasq dhcp-script hook.
|
|
#
|
|
# Runs every time a PXE client gets/changes/releases a DHCP lease on
|
|
# 172.16.9.0/24. Flushes conntrack entries and drops any lingering
|
|
# TCP sockets for that client IP. Prevents stale server-side state from
|
|
# causing "System error 53 - network path not found" when a WinPE client
|
|
# re-images the same machine without a clean SMB session teardown.
|
|
#
|
|
# dnsmasq calls this with argv:
|
|
# $1 = action (add | old | del)
|
|
# $2 = mac address
|
|
# $3 = client IP
|
|
# $4 = hostname (may be empty)
|
|
#
|
|
# A re-image usually comes back to the SAME lease (same MAC, same IP), which
|
|
# dnsmasq reports as "old", not "add" - and only at all because dnsmasq.conf
|
|
# sets script-on-renewal. "old" also fires when a running Windows PC renews
|
|
# its lease, so on "old" we only clear state when the request came from PXE
|
|
# firmware or iPXE (vendor class PXEClient...): that machine has just
|
|
# rebooted into a network boot, so any server-side session for its IP is
|
|
# dead. A renewal from Windows (vendor class "MSFT 5.0") is left alone.
|
|
#
|
|
# Must exit quickly; dnsmasq waits for it. Logs to syslog via logger.
|
|
|
|
set +e
|
|
|
|
action="$1"
|
|
mac="$2"
|
|
ip="$3"
|
|
host="${4:-}"
|
|
|
|
[ -z "$ip" ] && exit 0
|
|
|
|
clear_state() {
|
|
/usr/sbin/conntrack -D -s "$ip" >/dev/null 2>&1
|
|
/usr/sbin/conntrack -D -d "$ip" >/dev/null 2>&1
|
|
/usr/bin/ss -K "dst = $ip" >/dev/null 2>&1
|
|
/usr/bin/ss -K "src = $ip" >/dev/null 2>&1
|
|
logger -t pxe-dhcp-hook "cleared stale state for $1 $ip ($mac${host:+ $host})"
|
|
}
|
|
|
|
case "$action" in
|
|
add|del)
|
|
clear_state "$action"
|
|
;;
|
|
old)
|
|
case "${DNSMASQ_VENDOR_CLASS:-}" in
|
|
PXEClient*) clear_state "old (network boot, ${DNSMASQ_VENDOR_CLASS%%:UNDI*})" ;;
|
|
esac
|
|
;;
|
|
esac
|
|
|
|
exit 0
|