update-dnsmasq 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. #!/bin/bash
  2. # =============================================================================
  3. # Refresh dnsmasq config from /opt/Eye/scripts/print-dnsmasq.pl
  4. # Triggers restart if dhcp-host=, address=, or ptr-record= lines change.
  5. # =============================================================================
  6. # set -euo pipefail # Fail fast on error, undefined var, or pipe failure
  7. logger -t dnsmasq-refresh "Config refresh requested"
  8. force="${1:-}"
  9. # --- 1. Generate new config ---
  10. /opt/Eye/scripts/print-dnsmasq.pl > /tmp/mac-all.new
  11. ret=$?
  12. if [ ${ret} -ne 0 ]; then
  13. rm -f /tmp/mac-all.new
  14. logger -t dnsmasq-refresh "ERROR: Config generation failed (exit $ret). Aborting."
  15. exit 1
  16. fi
  17. # Ensure target dir exists
  18. [ -d /etc/dnsmasq.d ] || mkdir -p /etc/dnsmasq.d
  19. # --- 2. Compare with current config ---
  20. # Use existing file or empty if missing
  21. current_file="/etc/dnsmasq.d/mac-all"
  22. tmp_new="/tmp/mac-all.new"
  23. tmp_old="/tmp/mac-all.old"
  24. # Always have a baseline for diff (even if file missing)
  25. if [ -f "$current_file" ]; then
  26. cp "$current_file" "$tmp_old"
  27. else
  28. touch "$tmp_old"
  29. fi
  30. # Get diff of relevant lines only
  31. diff_output=$(diff -u "$tmp_old" "$tmp_new" 2>/dev/null || true)
  32. # Extract changed lines with our directives
  33. changed_lines=$(echo "$diff_output" | grep -E "^[+-](dhcp-host|address|ptr-record)=" || true)
  34. # Extract MACs (only from dhcp-host) for lease cleanup
  35. changes_macs=$(echo "$changed_lines" | grep "^[+-]dhcp-host=" | \
  36. sed -E 's/^[+-]dhcp-host=//' | cut -d',' -f1 | \
  37. grep -Eo '^([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}$' | sort -u)
  38. # Check if address= or ptr-record= changed
  39. if echo "$changed_lines" | grep -q "^[+-]\(address\|ptr-record\)="; then
  40. need_restart="yes"
  41. fi
  42. # --- 3. Decide: restart or skip? ---
  43. if [ -n "${changes_macs}" ] || [ -n "${need_restart:-}" ] || [ -n "${force:-}" ]; then
  44. logger -t dnsmasq-refresh "Changes detected. Updating config..."
  45. # --- ATOMIC REPLACE: delete → copy ---
  46. rm -f "$current_file"
  47. /bin/cp "$tmp_new" "$current_file"
  48. # --- Validate new config ---
  49. if /usr/sbin/dnsmasq --test >/dev/null 2>&1; then
  50. logger -t dnsmasq-refresh "Config OK. Restarting dnsmasq..."
  51. # Stop dnsmasq
  52. if ! systemctl stop dnsmasq >/dev/null 2>&1; then
  53. logger -t dnsmasq-refresh "WARNING: Failed to stop dnsmasq (maybe not running?)"
  54. fi
  55. # Clear leases for changed MACs
  56. if [ -n "${changes_macs}" ] && [ -f /var/lib/misc/dnsmasq.leases ]; then
  57. while IFS= read -r mac; do
  58. [ -z "$mac" ] && continue
  59. logger -t dnsmasq-refresh "Clearing lease for ${mac}"
  60. sed -i "/${mac}/d" /var/lib/misc/dnsmasq.leases 2>/dev/null || true
  61. done <<< "${changes_macs}"
  62. fi
  63. # Start dnsmasq
  64. if systemctl start dnsmasq >/dev/null 2>&1; then
  65. logger -t dnsmasq-refresh "SUCCESS: dnsmasq restarted"
  66. else
  67. logger -t dnsmasq-refresh "CRITICAL: dnsmasq failed to start! Rolling back..."
  68. rm -f "$current_file"
  69. [ -f "$tmp_old" ] && /bin/cp "$tmp_old" "$current_file"
  70. systemctl start dnsmasq >/dev/null 2>&1 || \
  71. logger -t dnsmasq-refresh "Rollback config applied, but dnsmasq still failed to start!"
  72. exit 1
  73. fi
  74. else
  75. logger -t dnsmasq-refresh "ERROR: dnsmasq config test failed! Rolling back..."
  76. rm -f "$current_file"
  77. [ -f "$tmp_old" ] && /bin/cp "$tmp_old" "$current_file"
  78. systemctl restart dnsmasq >/dev/null 2>&1 || true
  79. exit 1
  80. fi
  81. else
  82. logger -t dnsmasq-refresh "No relevant changes. Skipping restart."
  83. fi
  84. # --- Cleanup ---
  85. rm -f "$tmp_new" "$tmp_old"
  86. logger -t dnsmasq-refresh "Done."
  87. exit 0