diff --git a/playbook/pxe-server-helpers/pxe-dhcp-hook.sh b/playbook/pxe-server-helpers/pxe-dhcp-hook.sh new file mode 100755 index 0000000..5162266 --- /dev/null +++ b/playbook/pxe-server-helpers/pxe-dhcp-hook.sh @@ -0,0 +1,38 @@ +#!/bin/bash +# +# pxe-dhcp-hook.sh - dnsmasq dhcp-script hook. +# +# Runs every time a PXE client gets/changes/releases a DHCP lease on +# 10.9.100.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) +# +# 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 + +case "$action" in + add|del) + /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 $action $ip ($mac${host:+ $host})" + ;; +esac + +exit 0 diff --git a/playbook/pxe_server_setup.yml b/playbook/pxe_server_setup.yml index ff84a25..71200c6 100644 --- a/playbook/pxe_server_setup.yml +++ b/playbook/pxe_server_setup.yml @@ -125,6 +125,12 @@ register: disk_expand changed_when: "'CHANGED' in disk_expand.stdout or 'resized' in disk_expand.stdout" + - name: "Deploy dnsmasq dhcp-script for per-lease state cleanup" + copy: + src: "{{ usb_mount }}/pxe-server-helpers/pxe-dhcp-hook.sh" + dest: /usr/local/sbin/pxe-dhcp-hook.sh + mode: '0755' + - name: "Configure dnsmasq for DHCP and TFTP" copy: dest: /etc/dnsmasq.conf @@ -140,6 +146,11 @@ tftp-root={{ tftp_dir }} dhcp-boot=ipxe.efi log-dhcp + # Per-lease state cleanup: flush conntrack + port-445 sockets for + # the client IP on add/del. Prevents "System error 53" when a PXE + # client re-images the same machine and hits a stale SMB session. + # Script runs as root by default (dnsmasq --dhcp-scriptuser default). + dhcp-script=/usr/local/sbin/pxe-dhcp-hook.sh - name: "Create TFTP directory" file: diff --git a/playbook/startnet.cmd b/playbook/startnet.cmd index df1df23..a5f9cbf 100644 --- a/playbook/startnet.cmd +++ b/playbook/startnet.cmd @@ -66,14 +66,28 @@ echo 5. Pro Plus Office (x64) with Access echo 6. Skip enrollment echo. set /p enroll=Enter your choice (1-6): -if "%enroll%"=="1" set PPKG=GCCH_Prod_SFLD_NoOffice_US_Exp_20260430_v4.10.ppkg -if "%enroll%"=="2" set PPKG=GCCH_Prod_SFLD_StdOffice-x86_US_Exp_20260430_v4.10.ppkg -if "%enroll%"=="3" set PPKG=GCCH_Prod_SFLD_StdOffice-x64_US_Exp_20260430_v4.10.ppkg -if "%enroll%"=="4" set PPKG=GCCH_Prod_SFLD_ProPlusOffice-x86_US_Exp_20260430_v4.10.ppkg -if "%enroll%"=="5" set PPKG=GCCH_Prod_SFLD_ProPlusOffice-x64_US_Exp_20260430_v4.10.ppkg -if "%enroll%"=="6" set PPKG= + +REM --- PPKG configuration (constructed at menu time, see docs) --- +REM Vendor ships one source PPKG; we construct the BPRT-tagged filename +REM by filling in Office, Region, Expiry, Version on the target copy. +REM Update SOURCE_PPKG + PPKG_VER when a new PPKG is released. +set SOURCE_PPKG=GCCH_Prod_SFLD_v4.11.ppkg +set PPKG_VER=v4.11 +set PPKG_EXP=20270430 +set REGION=US + +set OFFICE= +if "%enroll%"=="1" set OFFICE=NoOffice +if "%enroll%"=="2" set OFFICE=StdOffice-x86 +if "%enroll%"=="3" set OFFICE=StdOffice-x64 +if "%enroll%"=="4" set OFFICE=ProPlusOffice-x86 +if "%enroll%"=="5" set OFFICE=ProPlusOffice-x64 +if "%enroll%"=="6" set OFFICE= if "%enroll%"=="" goto enroll_menu +set PPKG= +if not "%OFFICE%"=="" set PPKG=GCCH_Prod_SFLD_%OFFICE%_%REGION%_Exp_%PPKG_EXP%_%PPKG_VER%.ppkg + :pctype_menu cls echo. @@ -158,8 +172,8 @@ if not "%PCTYPE%"=="" set NEED_ENROLL=1 if "%NEED_ENROLL%"=="0" goto enroll_staged net use Y: \\10.9.100.1\enrollment /user:pxe-upload pxe /persistent:no if "%PPKG%"=="" goto enroll_staged -if not exist "Y:\ppkgs\%PPKG%" ( - echo WARNING: %PPKG% not found on server. Enrollment will be skipped. +if not exist "Y:\ppkgs\%SOURCE_PPKG%" ( + echo WARNING: %SOURCE_PPKG% not found on server. Enrollment will be skipped. set PPKG= ) :enroll_staged @@ -258,9 +272,9 @@ if exist "Y:\config\site-config.json" ( echo WARNING: site-config.json not found on enrollment share. ) -REM --- Copy PPKG if selected --- +REM --- Copy PPKG if selected (renames from SOURCE to BPRT-tagged filename) --- if "%PPKG%"=="" goto copy_pctype -copy /Y "Y:\ppkgs\%PPKG%" "W:\Enrollment\%PPKG%" +copy /Y "Y:\ppkgs\%SOURCE_PPKG%" "W:\Enrollment\%PPKG%" if errorlevel 1 ( echo WARNING: Failed to copy enrollment package. goto copy_pctype diff --git a/startnet-template.cmd b/startnet-template.cmd index df1df23..a5f9cbf 100644 --- a/startnet-template.cmd +++ b/startnet-template.cmd @@ -66,14 +66,28 @@ echo 5. Pro Plus Office (x64) with Access echo 6. Skip enrollment echo. set /p enroll=Enter your choice (1-6): -if "%enroll%"=="1" set PPKG=GCCH_Prod_SFLD_NoOffice_US_Exp_20260430_v4.10.ppkg -if "%enroll%"=="2" set PPKG=GCCH_Prod_SFLD_StdOffice-x86_US_Exp_20260430_v4.10.ppkg -if "%enroll%"=="3" set PPKG=GCCH_Prod_SFLD_StdOffice-x64_US_Exp_20260430_v4.10.ppkg -if "%enroll%"=="4" set PPKG=GCCH_Prod_SFLD_ProPlusOffice-x86_US_Exp_20260430_v4.10.ppkg -if "%enroll%"=="5" set PPKG=GCCH_Prod_SFLD_ProPlusOffice-x64_US_Exp_20260430_v4.10.ppkg -if "%enroll%"=="6" set PPKG= + +REM --- PPKG configuration (constructed at menu time, see docs) --- +REM Vendor ships one source PPKG; we construct the BPRT-tagged filename +REM by filling in Office, Region, Expiry, Version on the target copy. +REM Update SOURCE_PPKG + PPKG_VER when a new PPKG is released. +set SOURCE_PPKG=GCCH_Prod_SFLD_v4.11.ppkg +set PPKG_VER=v4.11 +set PPKG_EXP=20270430 +set REGION=US + +set OFFICE= +if "%enroll%"=="1" set OFFICE=NoOffice +if "%enroll%"=="2" set OFFICE=StdOffice-x86 +if "%enroll%"=="3" set OFFICE=StdOffice-x64 +if "%enroll%"=="4" set OFFICE=ProPlusOffice-x86 +if "%enroll%"=="5" set OFFICE=ProPlusOffice-x64 +if "%enroll%"=="6" set OFFICE= if "%enroll%"=="" goto enroll_menu +set PPKG= +if not "%OFFICE%"=="" set PPKG=GCCH_Prod_SFLD_%OFFICE%_%REGION%_Exp_%PPKG_EXP%_%PPKG_VER%.ppkg + :pctype_menu cls echo. @@ -158,8 +172,8 @@ if not "%PCTYPE%"=="" set NEED_ENROLL=1 if "%NEED_ENROLL%"=="0" goto enroll_staged net use Y: \\10.9.100.1\enrollment /user:pxe-upload pxe /persistent:no if "%PPKG%"=="" goto enroll_staged -if not exist "Y:\ppkgs\%PPKG%" ( - echo WARNING: %PPKG% not found on server. Enrollment will be skipped. +if not exist "Y:\ppkgs\%SOURCE_PPKG%" ( + echo WARNING: %SOURCE_PPKG% not found on server. Enrollment will be skipped. set PPKG= ) :enroll_staged @@ -258,9 +272,9 @@ if exist "Y:\config\site-config.json" ( echo WARNING: site-config.json not found on enrollment share. ) -REM --- Copy PPKG if selected --- +REM --- Copy PPKG if selected (renames from SOURCE to BPRT-tagged filename) --- if "%PPKG%"=="" goto copy_pctype -copy /Y "Y:\ppkgs\%PPKG%" "W:\Enrollment\%PPKG%" +copy /Y "Y:\ppkgs\%SOURCE_PPKG%" "W:\Enrollment\%PPKG%" if errorlevel 1 ( echo WARNING: Failed to copy enrollment package. goto copy_pctype