| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107 |
- #!/bin/bash
- # =============================================================================
- # Refresh dnsmasq config from /opt/Eye/scripts/print-dnsmasq.pl
- # Triggers restart if dhcp-host=, address=, or ptr-record= lines change.
- # =============================================================================
- # set -euo pipefail # Fail fast on error, undefined var, or pipe failure
- logger -t dnsmasq-refresh "Config refresh requested"
- force="${1:-}"
- # --- 1. Generate new config ---
- /opt/Eye/scripts/print-dnsmasq.pl > /tmp/mac-all.new
- ret=$?
- if [ ${ret} -ne 0 ]; then
- rm -f /tmp/mac-all.new
- logger -t dnsmasq-refresh "ERROR: Config generation failed (exit $ret). Aborting."
- exit 1
- fi
- # Ensure target dir exists
- [ -d /etc/dnsmasq.d ] || mkdir -p /etc/dnsmasq.d
- # --- 2. Compare with current config ---
- # Use existing file or empty if missing
- current_file="/etc/dnsmasq.d/mac-all"
- tmp_new="/tmp/mac-all.new"
- tmp_old="/tmp/mac-all.old"
- # Always have a baseline for diff (even if file missing)
- if [ -f "$current_file" ]; then
- cp "$current_file" "$tmp_old"
- else
- touch "$tmp_old"
- fi
- # Get diff of relevant lines only
- diff_output=$(diff -u "$tmp_old" "$tmp_new" 2>/dev/null || true)
- # Extract changed lines with our directives
- changed_lines=$(echo "$diff_output" | grep -E "^[+-](dhcp-host|address|ptr-record)=" || true)
- # Extract MACs (only from dhcp-host) for lease cleanup
- changes_macs=$(echo "$changed_lines" | grep "^[+-]dhcp-host=" | \
- sed -E 's/^[+-]dhcp-host=//' | cut -d',' -f1 | \
- grep -Eo '^([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}$' | sort -u)
- # Check if address= or ptr-record= changed
- if echo "$changed_lines" | grep -q "^[+-]\(address\|ptr-record\)="; then
- need_restart="yes"
- fi
- # --- 3. Decide: restart or skip? ---
- if [ -n "${changes_macs}" ] || [ -n "${need_restart:-}" ] || [ -n "${force:-}" ]; then
- logger -t dnsmasq-refresh "Changes detected. Updating config..."
- # --- ATOMIC REPLACE: delete → copy ---
- rm -f "$current_file"
- /bin/cp "$tmp_new" "$current_file"
- # --- Validate new config ---
- if /usr/sbin/dnsmasq --test >/dev/null 2>&1; then
- logger -t dnsmasq-refresh "Config OK. Restarting dnsmasq..."
- # Stop dnsmasq
- if ! systemctl stop dnsmasq >/dev/null 2>&1; then
- logger -t dnsmasq-refresh "WARNING: Failed to stop dnsmasq (maybe not running?)"
- fi
- # Clear leases for changed MACs
- if [ -n "${changes_macs}" ] && [ -f /var/lib/misc/dnsmasq.leases ]; then
- while IFS= read -r mac; do
- [ -z "$mac" ] && continue
- logger -t dnsmasq-refresh "Clearing lease for ${mac}"
- sed -i "/${mac}/d" /var/lib/misc/dnsmasq.leases 2>/dev/null || true
- done <<< "${changes_macs}"
- fi
- # Start dnsmasq
- if systemctl start dnsmasq >/dev/null 2>&1; then
- logger -t dnsmasq-refresh "SUCCESS: dnsmasq restarted"
- else
- logger -t dnsmasq-refresh "CRITICAL: dnsmasq failed to start! Rolling back..."
- rm -f "$current_file"
- [ -f "$tmp_old" ] && /bin/cp "$tmp_old" "$current_file"
- systemctl start dnsmasq >/dev/null 2>&1 || \
- logger -t dnsmasq-refresh "Rollback config applied, but dnsmasq still failed to start!"
- exit 1
- fi
- else
- logger -t dnsmasq-refresh "ERROR: dnsmasq config test failed! Rolling back..."
- rm -f "$current_file"
- [ -f "$tmp_old" ] && /bin/cp "$tmp_old" "$current_file"
- systemctl restart dnsmasq >/dev/null 2>&1 || true
- exit 1
- fi
- else
- logger -t dnsmasq-refresh "No relevant changes. Skipping restart."
- fi
- # --- Cleanup ---
- rm -f "$tmp_new" "$tmp_old"
- logger -t dnsmasq-refresh "Done."
- exit 0
|