refactor: Add graceful shutdown handling for dnsmasq reconfiguration

This commit is contained in:
Andrey Petelin
2025-09-11 11:43:58 +05:00
parent 49f12b212d
commit 5a2ffcfd38
2 changed files with 73 additions and 72 deletions

View File

@@ -43,4 +43,5 @@ config main 'main'
#list restart_ifaces 'wan' #list restart_ifaces 'wan'
option procd_reload_delay '2000' option procd_reload_delay '2000'
option ss_uot '0' option ss_uot '0'
option detour '0' option detour '0'
option shutdown_correctly '1'

View File

@@ -97,13 +97,18 @@ start() {
config_get interface "main" "interface" config_get interface "main" "interface"
config_get outbound_json "main" "outbound_json" config_get outbound_json "main" "outbound_json"
if [ -n "$proxy_string" ] || [ -n "$interface" ] || [ -n "$outbound_json" ]; then if [ -z "$proxy_string" ] && [ -z "$interface" ] && [ -z "$outbound_json" ]; then
start_main log "Podkop start aborted: required options (proxy_string, interface, outbound_json) are missing in 'main' section"
config_get_bool dont_touch_dhcp "main" "dont_touch_dhcp" 0 exit 1
if [ "$dont_touch_dhcp" -eq 0 ]; then
dnsmasq_add_resolver
fi
fi fi
start_main
config_get_bool dont_touch_dhcp "main" "dont_touch_dhcp" 0
if [ "$dont_touch_dhcp" -eq 0 ]; then
dnsmasq_add_resolver
fi
uci_set "podkop" "main" "shutdown_correctly" 0
uci commit "podkop"
} }
stop_main() { stop_main() {
@@ -143,12 +148,13 @@ stop_main() {
stop() { stop() {
local dont_touch_dhcp local dont_touch_dhcp
config_get_bool dont_touch_dhcp "main" "dont_touch_dhcp" "0" config_get_bool dont_touch_dhcp "main" "dont_touch_dhcp" 0
if [ "$dont_touch_dhcp" -eq 0 ]; then if [ "$dont_touch_dhcp" -eq 0 ]; then
dnsmasq_restore dnsmasq_restore
fi fi
stop_main stop_main
uci_set "podkop" "main" "shutdown_correctly" 1
uci commit "podkop"
} }
reload() { reload() {
@@ -306,7 +312,7 @@ create_nft_table() {
log "Create nft table" log "Create nft table"
nft_create_table "$NFT_TABLE_NAME" nft_create_table "$NFT_TABLE_NAME"
nft_interfaces nft_init_interfaces_set
log "Create localv4 set" log "Create localv4 set"
nft_create_ipv4_set "$NFT_TABLE_NAME" "$NFT_LOCALV4_SET_NAME" nft_create_ipv4_set "$NFT_TABLE_NAME" "$NFT_LOCALV4_SET_NAME"
@@ -347,89 +353,87 @@ create_nft_table() {
nft add rule inet "$NFT_TABLE_NAME" mangle_output ip daddr "$SB_FAKEIP_INET4_RANGE" meta l4proto '{ tcp, udp }' meta mark set 0x105 counter nft add rule inet "$NFT_TABLE_NAME" mangle_output ip daddr "$SB_FAKEIP_INET4_RANGE" meta l4proto '{ tcp, udp }' meta mark set 0x105 counter
} }
save_dnsmasq_config() { backup_dnsmasq_config_option() {
local key="$1" local key="$1"
local backup_key="$2" local backup_key="$2"
value=$(uci get "$key" 2>/dev/null) local value
value="$(uci_get "dhcp" "@dnsmasq[0]" "$key")"
if [ -z "$value" ]; then if [ -n "$value" ]; then
uci set "$backup_key"="unset" uci_set "dhcp" "@dnsmasq[0]" "$backup_key" "$value"
else
uci set "$backup_key"="$value"
fi fi
} }
dnsmasq_add_resolver() { dnsmasq_add_resolver() {
log "Save dnsmasq config" local shutdown_correctly
config_get shutdown_correctly "main" "shutdown_correctly"
if [ "$shutdown_correctly" -eq 0 ]; then
log "Previous shutdown of podkop was not correct, reconfiguration of dnsmasq is not required"
return 0
fi
uci -q delete dhcp.@dnsmasq[0].podkop_server log "Backup dnsmasq configuration"
for server in $(uci get dhcp.@dnsmasq[0].server 2>/dev/null); do current_servers="$(uci_get "dhcp" "@dnsmasq[0]" "server")"
if ! [ "$server" == "$SB_DNS_INBOUND_ADDRESS" ]; then if [ -n "$current_servers" ]; then
uci add_list dhcp.@dnsmasq[0].podkop_server="$server" for server in $(uci_get "dhcp" "@dnsmasq[0]" "server"); do
fi if ! [ "$server" == "$SB_DNS_INBOUND_ADDRESS" ]; then
done uci_add_list "dhcp" "@dnsmasq[0]" "podkop_server" "$server"
fi
done
uci_remove "dhcp" "@dnsmasq[0]" "server"
fi
save_dnsmasq_config "dhcp.@dnsmasq[0].noresolv" "dhcp.@dnsmasq[0].podkop_noresolv" backup_dnsmasq_config_option "noresolv" "podkop_noresolv"
save_dnsmasq_config "dhcp.@dnsmasq[0].cachesize" "dhcp.@dnsmasq[0].podkop_cachesize" backup_dnsmasq_config_option "cachesize" "podkop_cachesize"
log "Configure dnsmasq for sing-box" log "Configure dnsmasq for sing-box"
uci -q delete dhcp.@dnsmasq[0].server uci_add_list "dhcp" "@dnsmasq[0]" "server" "$SB_DNS_INBOUND_ADDRESS"
uci add_list dhcp.@dnsmasq[0].server="$SB_DNS_INBOUND_ADDRESS" uci_set "dhcp" "@dnsmasq[0]" "noresolv" 1
uci set dhcp.@dnsmasq[0].noresolv="1" uci_set "dhcp" "@dnsmasq[0]" "cachesize" 0
uci set dhcp.@dnsmasq[0].cachesize="0" uci_commit "dhcp"
uci commit dhcp
/etc/init.d/dnsmasq restart /etc/init.d/dnsmasq restart
} }
dnsmasq_restore() { dnsmasq_restore() {
log "Restoring the dnsmasq configuration" log "Restoring the dnsmasq configuration"
local shutdown_correctly
local cachesize noresolv current_servers backup_servers found_in_backup config_get shutdown_correctly "main" "shutdown_correctly"
cachesize=$(uci get dhcp.@dnsmasq[0].podkop_cachesize 2>/dev/null) if [ "$shutdown_correctly" -eq 1 ]; then
if [[ "$cachesize" == "unset" ]]; then log "Previous shutdown of podkop was correct, reconfiguration of dnsmasq is not required"
log "Cachesize is unset" "debug" return 0
uci -q delete dhcp.@dnsmasq[0].cachesize
else
uci set dhcp.@dnsmasq[0].cachesize="$cachesize"
fi fi
uci delete dhcp.@dnsmasq[0].podkop_cachesize
noresolv=$(uci get dhcp.@dnsmasq[0].podkop_noresolv 2>/dev/null) local cachesize noresolv backup_servers
if [[ "$noresolv" == "unset" ]]; then log "Restoring cachesize" "debug"
log "Noresolv is unset" "debug" cachesize="$(uci_get "dhcp" "@dnsmasq[0]" "podkop_cachesize")"
uci -q delete dhcp.@dnsmasq[0].noresolv if [ -z "$cachesize" ]; then
uci_remove "dhcp" "@dnsmasq[0]" "cachesize"
else else
uci set dhcp.@dnsmasq[0].noresolv="$noresolv" uci_set "dhcp" "@dnsmasq[0]" "cachesize" "$cachesize"
uci_remove "dhcp" "@dnsmasq[0]" "podkop_cachesize"
fi fi
uci delete dhcp.@dnsmasq[0].podkop_noresolv
current_servers=$(uci get dhcp.@dnsmasq[0].server 2>/dev/null) log "Restoring noresolv" "debug"
backup_servers=$(uci get dhcp.@dnsmasq[0].podkop_server 2>/dev/null) noresolv="$(uci_get "dhcp" "@dnsmasq[0]" "podkop_noresolv")"
uci -q delete dhcp.@dnsmasq[0].server 2>/dev/null if [ -z "$noresolv" ]; then
for server in $current_servers; do uci_remove "dhcp" "@dnsmasq[0]" "noresolv"
[ "$server" = "$SB_DNS_INBOUND_ADDRESS" ] && continue else
uci_set "dhcp" "@dnsmasq[0]" "noresolv" "$noresolv"
uci_remove "dhcp" "@dnsmasq[0]" "podkop_noresolv"
fi
found_in_backup=0 log "Restoring DNS servers" "debug"
for backup_server in $backup_servers; do uci_remove "dhcp" "@dnsmasq[0]" "server"
if [ "$server" = "$backup_server" ]; then backup_servers="$(uci_get "dhcp" "@dnsmasq[0]" "podkop_server")"
found_in_backup=1 if [ -n "$backup_servers" ]; then
break for server in $backup_servers; do
fi uci_add_list "dhcp" "@dnsmasq[0]" "server" "$server"
done done
uci_remove "dhcp" "@dnsmasq[0]" "podkop_server"
fi
[ "$found_in_backup" -eq 1 ] && continue uci_commit "dhcp"
uci add_list dhcp.@dnsmasq[0].server="$server"
done
backup_servers=$(uci get dhcp.@dnsmasq[0].podkop_server 2>/dev/null)
for server in $backup_servers; do
uci add_list dhcp.@dnsmasq[0].server="$server"
done
uci delete dhcp.@dnsmasq[0].podkop_server 2>/dev/null
uci commit dhcp
/etc/init.d/dnsmasq restart /etc/init.d/dnsmasq restart
} }
@@ -587,10 +591,6 @@ sing_box_init_config() {
sing_box_configure_route sing_box_configure_route
sing_box_configure_experimental sing_box_configure_experimental
sing_box_additional_inbounds sing_box_additional_inbounds
# TODO: remove after refactoring
nolog "$config"
sing_box_save_config sing_box_save_config
} }