adblock-fast: update to 1.1.2-1
authorRISCi_ATOM <bob@bobcall.me>
Wed, 5 Jun 2024 22:16:30 +0000 (18:16 -0400)
committerRISCi_ATOM <bob@bobcall.me>
Wed, 5 Jun 2024 22:16:30 +0000 (18:16 -0400)
* move extra_command and EXTRA_HELP to the top of the init file
* add packageCompat variable for compatibility check with WebUI
* add OutputFilter variables for supported resolvers
* simplify adb_check with the use of OutputFilter variables
* add show_blocklist command to display currently blocked domains

package/network/config/adblock-fast/Makefile
package/network/config/adblock-fast/files/etc/init.d/adblock-fast

index a5d137b39d82bc89b09e89249f5534af7356ffe0..4bb127854969f9d8ffea1a30a92bc5005500c9a3 100644 (file)
@@ -1,14 +1,14 @@
-# Copyright 2023 MOSSDeF, Stan Grishin (stangri@melmac.ca)
-# TLD optimization written by Dirk Brenken (dev@brenken.org)
-# This is free software, licensed under the GNU General Public License v3.
+# Copyright 2023-2024 MOSSDeF, Stan Grishin (stangri@melmac.ca).
+# TLD optimization written by Dirk Brenken (dev@brenken.org).
+# This is free software, licensed under AGPL-3.0-or-later.
 
 include $(TOPDIR)/rules.mk
 
 PKG_NAME:=adblock-fast
-PKG_VERSION:=1.1.1
+PKG_VERSION:=1.1.2
 PKG_RELEASE:=1
 PKG_MAINTAINER:=Stan Grishin <stangri@melmac.ca>
-PKG_LICENSE:=GPL-3.0-or-later
+PKG_LICENSE:=AGPL-3.0-or-later
 
 include $(INCLUDE_DIR)/package.mk
 
@@ -69,10 +69,11 @@ define Package/adblock-fast/prerm
        #!/bin/sh
        # check if we are on real system
        if [ -z "$${IPKG_INSTROOT}" ]; then
-               echo "Stopping service and removing rc.d symlink for adblock-fast"
-               /etc/init.d/adblock-fast stop || true
-               /etc/init.d/adblock-fast killcache || true
-               /etc/init.d/adblock-fast disable || true
+               echo -n "Stopping adblock-fast service... "
+               { /etc/init.d/adblock-fast stop && \
+                 /etc/init.d/adblock-fast killcache; } >/dev/null 2>&1 && echo "OK" || echo "FAIL"
+               echo -n "Removing rc.d symlink for adblock-fast... "
+               /etc/init.d/adblock-fast disable >/dev/null 2>&1 && echo "OK" || echo "FAIL"
        fi
        exit 0
 endef
index bb09717705e71fe2347b8c425e6cfe61fe346095..996bfa2b3e2b9e05cb6917d4c09766ef7d3f089c 100755 (executable)
@@ -8,8 +8,33 @@ START=94
 USE_PROCD=1
 LC_ALL=C
 
-readonly PKG_VERSION='dev-test'
+if type extra_command 1>/dev/null 2>&1; then
+       extra_command 'allow' 'Allows domain in current block-list and config'
+       extra_command 'check' 'Checks if specified domain is found in current block-list'
+       extra_command 'check_lists' 'Checks if specified domain is found in enabled block-lists'
+       extra_command 'dl' 'Force-downloads all enabled block-list'
+       extra_command 'killcache' 'Delete all cached files'
+       extra_command 'pause' 'Pauses AdBlocking for specified number of seconds (default: 60)'
+       extra_command 'show_blocklist' 'List currently blocked domains'
+       extra_command 'sizes' 'Displays the file-sizes of enabled block-lists'
+       extra_command 'version' 'Show version information'
+else
+# shellcheck disable=SC2034
+       EXTRA_COMMANDS='allow check dl killcache pause sizes status_service version'
+# shellcheck disable=SC2034
+       EXTRA_HELP='    allow   Allows domain(s) in current block-list and config
+       check   Checks if specified domain is found in current block-list
+       check_lists     Checks if specified domain is found in enabled block-lists
+       dl      Force-downloads all enabled block-list
+       pause   Pauses AdBlocking for specified number of seconds (default: 60)
+       show_blocklist  List currently blocked domains
+       sizes   Displays the file-sizes of enabled block-lists
+       version Show version information'
+fi
+
 readonly packageName='adblock-fast'
+readonly PKG_VERSION='dev-test'
+readonly packageCompat='1'
 readonly serviceName="$packageName $PKG_VERSION"
 readonly packageConfigFile="/etc/config/${packageName}"
 readonly dnsmasqAddnhostsFile="/var/run/${packageName}/dnsmasq.addnhosts"
@@ -17,50 +42,60 @@ readonly dnsmasqAddnhostsCache="/var/run/${packageName}/dnsmasq.addnhosts.cache"
 readonly dnsmasqAddnhostsGzip="${packageName}.dnsmasq.addnhosts.gz"
 readonly dnsmasqAddnhostsFilter='s|^|127.0.0.1 |;s|$||'
 readonly dnsmasqAddnhostsFilterIPv6='s|^|:: |;s|$||'
+readonly dnsmasqAddnhostsOutputFilter='s|^127.0.0.1 ||;s|^:: ||;'
 readonly dnsmasqConfFile="/tmp/dnsmasq.d/${packageName}"
 readonly dnsmasqConfCache="/var/run/${packageName}/dnsmasq.conf.cache"
 readonly dnsmasqConfGzip="${packageName}.dnsmasq.conf.gz"
 readonly dnsmasqConfFilter='s|^|local=/|;s|$|/|'
+readonly dnsmasqConfOutputFilter='s|local=/||;s|/$||;'
 readonly dnsmasqIpsetFile="/tmp/dnsmasq.d/${packageName}.ipset"
 readonly dnsmasqIpsetCache="/var/run/${packageName}/dnsmasq.ipset.cache"
 readonly dnsmasqIpsetGzip="${packageName}.dnsmasq.ipset.gz"
 readonly dnsmasqIpsetFilter='s|^|ipset=/|;s|$|/adb|'
+readonly dnsmasqIpsetOutputFilter='s|ipset=/||;s|/adb$||;'
 readonly dnsmasqNftsetFile="/tmp/dnsmasq.d/${packageName}.nftset"
 readonly dnsmasqNftsetCache="/var/run/${packageName}/dnsmasq.nftset.cache"
 readonly dnsmasqNftsetGzip="${packageName}.dnsmasq.nftset.gz"
 readonly dnsmasqNftsetFilter='s|^|nftset=/|;s|$|/4#inet#fw4#adb4|'
 readonly dnsmasqNftsetFilterIPv6='s|^|nftset=/|;s|$|/4#inet#fw4#adb4,6#inet#fw4#adb6|'
+readonly dnsmasqNftsetOutputFilter='s|nftset=/||;s|/4#inet#adb#adb4||;'
 readonly dnsmasqServersFile="/var/run/${packageName}/dnsmasq.servers"
 readonly dnsmasqServersCache="/var/run/${packageName}/dnsmasq.servers.cache"
 readonly dnsmasqServersGzip="${packageName}.dnsmasq.servers.gz"
 readonly dnsmasqServersFilter='s|^|server=/|;s|$|/|'
+readonly dnsmasqServersOutputFilter='s|server=/||;s|/$||;'
 readonly smartdnsDomainSetFile="/var/run/${packageName}/smartdns.domainset"
 readonly smartdnsDomainSetCache="/var/run/${packageName}/smartdns.domainset.cache"
 readonly smartdnsDomainSetConfig="/var/run/${packageName}/smartdns.domainset.conf"
 readonly smartdnsDomainSetGzip="${packageName}.smartdns.domainset.gz"
-readonly smartdnsDomainSetFilter=';'
+readonly smartdnsDomainSetFilter=''
+readonly smartdnsDomainSetOutputFilter=''
 readonly smartdnsIpsetFile="/var/run/${packageName}/smartdns.ipset"
 readonly smartdnsIpsetCache="/var/run/${packageName}/smartdns.ipset.cache"
 readonly smartdnsIpsetConfig="/var/run/${packageName}/smartdns.ipset.conf"
 readonly smartdnsIpsetGzip="${packageName}.smartdns.ipset.gz"
-readonly smartdnsIpsetFilter=';'
+readonly smartdnsIpsetFilter=''
+readonly smartdnsIpsetOutputFilter=''
 readonly smartdnsNftsetFile="/var/run/${packageName}/smartdns.nftset"
 readonly smartdnsNftsetCache="/var/run/${packageName}/smartdns.nftset.cache"
 readonly smartdnsNftsetConfig="/var/run/${packageName}/smartdns.nftset.conf"
 readonly smartdnsNftsetGzip="${packageName}.smartdns.nftset.gz"
-readonly smartdnsNftsetFilter=';'
+readonly smartdnsNftsetFilter=''
+readonly smartdnsNftsetOutputFilter=''
 readonly unboundFile="/var/lib/unbound/adb_list.${packageName}"
 readonly unboundCache="/var/run/${packageName}/unbound.cache"
 readonly unboundGzip="${packageName}.unbound.gz"
-readonly unboundFilter='s|^|local-zone: "|;s|$|" static|'
+readonly unboundFilter='s|^|local-zone: "|;s|$|." always_nxdomain|'
+readonly unboundOutputFilter='s|^local-zone: "||;s|." always_nxdomain$||;'
 readonly A_TMP="/var/${packageName}.a.tmp"
 readonly B_TMP="/var/${packageName}.b.tmp"
 readonly SED_TMP="/var/${packageName}.sed.tmp"
+readonly uciConfigFile="/etc/config/${packageName}"
 readonly runningConfigFile="/dev/shm/${packageName}.config"
 readonly runningErrorFile="/dev/shm/${packageName}.error"
 readonly runningStatusFile="/dev/shm/${packageName}.status"
 readonly hostsFilter='/localhost/d;/^#/d;/^[^0-9]/d;s/^0\.0\.0\.0.//;s/^127\.0\.0\.1.//;s/[[:space:]]*#.*$//;s/[[:cntrl:]]$//;s/[[:space:]]//g;/[`~!@#\$%\^&\*()=+;:"'\'',<>?/\|[{}]/d;/]/d;/\./!d;/^$/d;/[^[:alnum:]_.-]/d;'
-readonly domainsFilter='/^#/d;s/[[:space:]]*#.*$//;s/[[:space:]]*$//;s/[[:cntrl:]]$//;/[[:space:]]/d;/[`~!@#\$%\^&\*()=+;:"'\'',<>?/\|[{}]/d;/]/d;/\./!d;/^$/d;/[^[:alnum:]_.-]/d;'
+readonly domainsFilter='/^#/d;s/[[:space:]]*#.*$//;s/[[:space:]]*$//;s/[[:cntrl:]]$//;/[[:space:]]/d;/[`~!@#\$%\^&\*()=+;:"'\'',<>?/\|[{}]/d;/]/d;/^$/d;/[^[:alnum:]_.-]/d;'
 readonly adBlockPlusFilter='/^#/d;/^!/d;s/[[:space:]]*#.*$//;s/^||//;s/\^$//;s/[[:space:]]*$//;s/[[:cntrl:]]$//;/[[:space:]]/d;/[`~!@#\$%\^&\*()=+;:"'\'',<>?/\|[{}]/d;/]/d;/\./!d;/^$/d;/[^[:alnum:]_.-]/d;'
 readonly dnsmasqFileFilter='\|^server=/[[:alnum:]_.-].*/|!d;s|server=/||;s|/.*$||'
 readonly dnsmasq2FileFilter='\|^local=/[[:alnum:]_.-].*/|!d;s|local=/||;s|/.*$||'
@@ -88,6 +123,7 @@ outputFilterIPv6=
 outputFile=
 outputGzip=
 outputCache=
+outputOutputFilter=
 awk='awk'
 load_environment_flag=
 allowed_url=
@@ -128,7 +164,7 @@ config_cache() {
        local i ret
        case "$param" in
                create|set)
-                       cp -f "/etc/config/${packageName}" "$runningConfigFile"
+                       cp -f "$uciConfigFile" "$runningConfigFile"
                ;;
                get)
                        case "$var" in
@@ -145,6 +181,8 @@ config_cache() {
                                local old_allowed_url old_blocked_url
                                if [ ! -s "$runningConfigFile" ]; then
                                        ret='on_boot'
+                               elif cmp -s "$uciConfigFile" "$runningConfigFile"; then
+                                       ret='restart'
                                else
                                        for i in $_reload; do
                                                local val_current val_old UCI_CONFIG_DIR
@@ -199,7 +237,7 @@ config_cache() {
        ;;
        esac
 }
-debug() { local i j; for i in "$@"; do eval "j=\$$i"; echo "${i}: ${j} "; done; }
+debug() { local __i __j; for __i in "$@"; do eval "__j=\$$__i"; echo "${__i}: ${__j} "; done; }
 dns_set_output_values() {
        case "$1" in
                dnsmasq.addnhosts)
@@ -207,6 +245,7 @@ dns_set_output_values() {
                        outputFile="$dnsmasqAddnhostsFile"
                        outputCache="$dnsmasqAddnhostsCache"
                        outputGzip="${compressed_cache_dir}/${dnsmasqAddnhostsGzip}"
+                       outputOutputFilter="$dnsmasqAddnhostsOutputFilter"
                        if [ "$ipv6_enabled" -ne '0' ]; then
                                outputFilterIPv6="$dnsmasqAddnhostsFilterIPv6"
                        fi
@@ -216,12 +255,14 @@ dns_set_output_values() {
                        outputFile="$dnsmasqConfFile"
                        outputCache="$dnsmasqConfCache"
                        outputGzip="${compressed_cache_dir}/${dnsmasqConfGzip}"
+                       outputOutputFilter="$dnsmasqConfOutputFilter"
                ;;
                dnsmasq.ipset)
                        outputFilter="$dnsmasqIpsetFilter"
                        outputFile="$dnsmasqIpsetFile"
                        outputCache="$dnsmasqIpsetCache"
                        outputGzip="${compressed_cache_dir}/${dnsmasqIpsetGzip}"
+                       outputOutputFilter="$dnsmasqIpsetOutputFilter"
                ;;
                dnsmasq.nftset)
                        if [ "$ipv6_enabled" -ne '0' ]; then
@@ -232,12 +273,14 @@ dns_set_output_values() {
                        outputFile="$dnsmasqNftsetFile"
                        outputCache="$dnsmasqNftsetCache"
                        outputGzip="${compressed_cache_dir}/${dnsmasqNftsetGzip}"
+                       outputOutputFilter="$dnsmasqNftsetOutputFilter"
                ;;
                dnsmasq.servers)
                        outputFilter="$dnsmasqServersFilter"
                        outputFile="$dnsmasqServersFile"
                        outputCache="$dnsmasqServersCache"
                        outputGzip="${compressed_cache_dir}/${dnsmasqServersGzip}"
+                       outputOutputFilter="$dnsmasqServersOutputFilter"
                ;;
                smartdns.domainset)
                        outputFilter="$smartdnsDomainSetFilter"
@@ -245,6 +288,7 @@ dns_set_output_values() {
                        outputCache="$smartdnsDomainSetCache"
                        outputGzip="${compressed_cache_dir}/${smartdnsDomainSetGzip}"
                        outputConfig="$smartdnsDomainSetConfig"
+                       outputOutputFilter="$smartdnsDomainSetOutputFilter"
                ;;
                smartdns.ipset)
                        outputFilter="$smartdnsIpsetFilter"
@@ -252,6 +296,7 @@ dns_set_output_values() {
                        outputCache="$smartdnsIpsetCache"
                        outputGzip="${compressed_cache_dir}/${smartdnsIpsetGzip}"
                        outputConfig="$smartdnsIpsetConfig"
+                       outputOutputFilter="$smartdnsIpsetOutputFilter"
                ;;
                smartdns.nftset)
                        outputFilter="$smartdnsNftsetFilter"
@@ -259,12 +304,14 @@ dns_set_output_values() {
                        outputCache="$smartdnsNftsetCache"
                        outputGzip="${compressed_cache_dir}/${smartdnsNftsetGzip}"
                        outputConfig="$smartdnsNftsetConfig"
+                       outputOutputFilter="$smartdnsNftsetOutputFilter"
                ;;
                unbound.adb_list)
                        outputFilter="$unboundFilter"
                        outputFile="$unboundFile"
                        outputCache="$unboundCache"
-                       outputGzip="$unboundGzip"
+                       outputGzip="${compressed_cache_dir}/${unboundGzip}"
+                       outputOutputFilter="$unboundOutputFilter"
                ;;
        esac
 }
@@ -315,7 +362,6 @@ is_running() {
        fi
 }
 ipset() { "$ipset" "$@" >/dev/null 2>&1; }
-get_version() { grep -m1 -A2 -w "^Package: $1$" /usr/lib/opkg/status | sed -n 's/Version: //p'; }
 get_ram_free() { ubus call system info | jsonfilter -e '@.memory.free'; }
 get_ram_total() { ubus call system info | jsonfilter -e '@.memory.total'; }
 led_on(){ if [ -n "${1}" ] && [ -e "${1}/trigger" ]; then echo 'default-on' > "${1}/trigger" 2>&1; fi; }
@@ -330,6 +376,7 @@ print_json_bool() { json_init; json_add_boolean "$1" "$2"; json_dump; json_clean
 print_json_int() { json_init; json_add_int "$1" "$2"; json_dump; json_cleanup; }
 print_json_string() { json_init; json_add_string "$1" "$2"; json_dump; json_cleanup; }
 sanitize_dir() { [ -d "$(readlink -fn "$1")" ] && readlink -fn "$1"; }
+smartdns_restart() { /etc/init.d/smartdns restart >/dev/null 2>&1; }
 str_contains() { test "$1" != "$(str_replace "$1" "$2" '')"; }
 str_contains_word() { echo "$1" | grep -q -w "$2"; }
 # shellcheck disable=SC2018,SC2019
@@ -339,6 +386,7 @@ str_to_upper() { echo "$1" | tr 'a-z' 'A-Z'; }
 str_replace() { printf "%b" "$1" | sed -e "s/$(printf "%b" "$2")/$(printf "%b" "$3")/g"; }
 ubus_get_data() { ubus call service list "{ 'name': '$packageName' }" | jsonfilter -e "@['${packageName}'].instances.main.data.${1}"; }
 ubus_get_ports() { ubus call service list "{ 'name': '$packageName' }" | jsonfilter -e "@['${packageName}'].instances.main.data.firewall.*.dest_port"; }
+uci_get_protocol() { uci_get 'network' "$1" 'proto'; }
 unbound_restart() { /etc/init.d/unbound restart >/dev/null 2>&1; }
 
 json() {
@@ -425,9 +473,8 @@ output() {
        local msg memmsg logmsg text
        local sharedMemoryOutput="/dev/shm/$packageName-output"
        if [ -z "$verbosity" ] && [ -n "$packageName" ]; then
-               verbosity="$(uci -q get "$packageName.config.verbosity")"
+               verbosity="$(uci_get "$packageName" 'config' 'verbosity' '2')"
        fi
-       verbosity="${verbosity:-2}"
        if [ $# -ne 1 ] && is_integer "$1"; then
                if [ $((verbosity & $1)) -gt 0 ] || [ "$verbosity" = "$1" ]; then shift; text="$*"; else return 0; fi
        fi
@@ -467,26 +514,6 @@ uci_changes() {
        fi
 }
 
-if type extra_command 1>/dev/null 2>&1; then
-       extra_command 'allow' 'Allows domain in current block-list and config'
-       extra_command 'check' 'Checks if specified domain is found in current block-list'
-       extra_command 'check_lists' 'Checks if specified domain is found in enabled block-lists'
-       extra_command 'dl' 'Force-downloads all enabled block-list'
-       extra_command 'killcache' 'Delete all cached files'
-       extra_command 'pause' 'Pauses AdBlocking for specified number of seconds (default: 60)'
-       extra_command 'sizes' 'Displays the file-sizes of enabled block-lists'
-       extra_command 'version' 'Show version information'
-else
-# shellcheck disable=SC2034
-       EXTRA_COMMANDS='allow check dl killcache pause sizes status_service version'
-# shellcheck disable=SC2034
-       EXTRA_HELP='    allow   Allows domain(s) in current block-list and config
-       check   Checks if specified domain is found in current block-list
-       dl      Force-downloads all enabled block-list
-       pause   Pauses AdBlocking for specified number of seconds (default: 60)
-       sizes   Displays the file-sizes of enabled block-lists'
-fi
-
 get_text() {
        local r
        case "$1" in
@@ -549,7 +576,7 @@ get_text() {
 
 load_network() {
        local param="$1"
-       local i j wan_if wan_gw wan_proto
+       local i j wan_if wan_gw
        local counter wan_if_timeout="$procd_boot_wan_timeout" wan_gw_timeout='5'
        counter=0
        while [ -z "$wan_if" ]; do
@@ -570,8 +597,7 @@ load_network() {
        done
 
        counter=0
-       wan_proto="$(uci -q get "network.${wan_if}.proto")"
-       if [ "$wan_proto" = 'pppoe' ]; then
+       if [ "$(uci_get_protocol "$wan_if")" = 'pppoe' ]; then
                wan_gw_timeout=$((wan_gw_timeout+10))
        fi
        while [ "$counter" -le "$wan_gw_timeout" ]; do
@@ -755,7 +781,7 @@ load_environment() {
        [ "$dns" = 'smartdns.domainset' ] || rm -f "$smartdnsDomainSetFile" "$smartdnsDomainSetCache" "${compressed_cache_dir}/${smartdnsDomainSetGzip}" "$smartdnsDomainSetConfig"
        [ "$dns" = 'smartdns.ipset' ]     || rm -f "$smartdnsIpsetFile" "$smartdnsIpsetCache" "${compressed_cache_dir}/${smartdnsIpsetGzip}" "$smartdnsIpsetConfig"
        [ "$dns" = 'smartdns.nftset' ]    || rm -f "$smartdnsNftsetFile" "$smartdnsNftsetCache" "${compressed_cache_dir}/${smartdnsNftsetGzip}" "$smartdnsNftsetConfig"
-       [ "$dns" = 'unbound.adb_list' ]   || rm -f "$unboundFile" "$unboundCache" "$unboundGzip"
+       [ "$dns" = 'unbound.adb_list' ]   || rm -f "$unboundFile" "$unboundCache" "${compressed_cache_dir}/${unboundGzip}"
 
        for i in "$runningConfigFile" "$runningErrorFile" "$runningStatusFile" "$outputFile" "$outputCache" "$outputGzip" "$outputConfig"; do
                [ -n "$i" ] || continue
@@ -807,11 +833,8 @@ load_environment() {
                dl_flag="-O"
        fi
        led="${led:+/sys/class/leds/$led}"
-       if curl --version 2>/dev/null | grep -q "https" \
-               || wget --version 2>/dev/null | grep -q "+https" \
-               || grep -q "libustream-mbedtls" /usr/lib/opkg/status \
-               || grep -q "libustream-openssl" /usr/lib/opkg/status \
-               || grep -q "libustream-wolfssl" /usr/lib/opkg/status; then
+       if curl --version 2>/dev/null | grep -q "Protocols: .*https.*" \
+               || wget --version 2>/dev/null | grep -q "+ssl"; then
                isSSLSupported=1
        else
                unset isSSLSupported
@@ -830,7 +853,7 @@ load_environment() {
 }
 
 resolver() {
-       _resolver_config() {
+       _dnsmasq_instance_config() {
                local cfg="$1" param="$2"
                [ -s "/etc/config/dhcp" ] || return 0
                case "$param" in
@@ -893,7 +916,7 @@ resolver() {
                        rm -f "$smartdnsDomainSetFile" "$smartdnsDomainSetCache" "${compressed_cache_dir}/${smartdnsDomainSetGzip}" "$smartdnsDomainSetConfig"
                        rm -f "$smartdnsIpsetFile" "$smartdnsIpsetCache" "${compressed_cache_dir}/${smartdnsIpsetGzip}" "$smartdnsIpsetConfig"
                        rm -f "$smartdnsNftsetFile" "$smartdnsNftsetCache" "${compressed_cache_dir}/${smartdnsNftsetGzip}" "$smartdnsNftsetConfig"
-                       rm -f "$unboundFile" "$unboundCache" "$unboundGzip"
+                       rm -f "$unboundFile" "$unboundCache" "${compressed_cache_dir}/${unboundGzip}"
                        if [ -s "/etc/config/dhcp" ]; then
                                config_load 'dhcp'
                                config_foreach _dnsmasq_instance_config 'dnsmasq' 'cleanup'
@@ -915,42 +938,54 @@ resolver() {
 
                        config_load 'dhcp'
                        if [ "$dnsmasq_instance" = "*" ]; then
-                               config_foreach _resolver_config 'dnsmasq' "$dns"
+                               config_foreach _dnsmasq_instance_config 'dnsmasq' "$dns"
                        elif [ -n "$dnsmasq_instance" ]; then
                                for i in $dnsmasq_instance; do
-                                       _resolver_config "@dnsmasq[$i]" "$dns" || _resolver_config "$i" "$dns"
+                                       _dnsmasq_instance_config "@dnsmasq[$i]" "$dns" || _dnsmasq_instance_config "$i" "$dns"
+                               done
+                       fi
+                       config_load 'smartdns'
+                       if [ "$smartdns_instance" = "*" ]; then
+                               config_foreach _smartdns_instance_config 'smartdns' "$dns"
+                       elif [ -n "$smartdns_instance" ]; then
+                               for i in $smartdns_instance; do
+                                       _smartdns_instance_config "@smartdns[$i]" "$dns" || _smartdns_instance_config "$i" "$dns"
                                done
                        fi
 
                        case "$dns" in
                                dnsmasq.*)
                                        chmod 660 "$outputFile"
-                                       chown root:dnsmasq "$outputFile"
-                                       param=dnsmasq_restart
+                                       chown root:dnsmasq "$outputFile" >/dev/null 2>/dev/null
+                                       param='dnsmasq_restart'
                                        output_text='Restarting dnsmasq'
                                ;;
                                smartdns.*)
                                        chmod 660 "$outputFile" "$outputConfig"
-                                       chown root:root "$outputFile" "$outputConfig"
+                                       chown root:root "$outputFile" "$outputConfig" >/dev/null 2>/dev/null
                                        param='smartdns_restart'
                                        output_text='Restarting SmartDNS'
                                ;;
                                unbound.*)
                                        chmod 660 "$outputFile"
-                                       chown root:unbound "$outputFile"
+                                       chown root:unbound "$outputFile" >/dev/null 2>/dev/null
                                        param='unbound_restart'
                                        output_text='Restarting Unbound'
                                ;;
                        esac
 
-                       if [ -n "$(uci_changes dhcp)" ]; then
-                               uci_commit dhcp
-                               if [ "$param" = 'unbound_restart' ]; then
-                                       param='dnsmasq_restart; unbound_restart;'
-                                       output_text='Restarting Unbound/dnsmasq'
-                               else
-                                       param=dnsmasq_restart
-                                       output_text='Restarting dnsmasq'
+                       if [ -n "$(uci_changes dhcp)" ]; then 
+                               uci_commit 'dhcp'
+                               if ! str_contains "$param" 'dnsmasq_restart'; then
+                                       param="${param:+"$param; dnsmasq_restart"}"
+                                       output_text="${output_text}/dnsmasq"
+                               fi
+                       fi
+                       if [ -n "$(uci_changes smartdns)" ]; then 
+                               uci_commit 'smartdns'
+                               if ! str_contains "$param" 'smartdns_restart'; then
+                                       param="${param:+"$param; "}smartdns_restart"
+                                       output_text="${output_text}/smartDNS"
                                fi
                        fi
                        output 1 "$output_text "
@@ -981,12 +1016,12 @@ resolver() {
                                ;;
                        esac
                        if [ -n "$(uci_changes dhcp)" ]; then 
-                               uci_commit dhcp
-                               if [ "$param" = 'unbound_restart' ]; then
-                                       param='dnsmasq_restart; unbound_restart;'
-                               else
-                                       param=dnsmasq_restart
-                               fi
+                               uci_commit 'dhcp'
+                               str_contains "$param" 'dnsmasq_restart' || param="${param:+"$param; dnsmasq_restart"}"
+                       fi
+                       if [ -n "$(uci_changes smartdns)" ]; then 
+                               uci_commit 'smartdns'
+                               str_contains "$param" 'smartdns_restart' || param="${param:+"$param; "}smartdns_restart"
                        fi
                        eval "$param"
                        return $?
@@ -1025,7 +1060,7 @@ cache() {
                        return $?
                ;;
                test_gzip)
-                       [ -s "$outputGzip" ] && gzip -t -c "$outputGzip"
+                       [ -s "$outputGzip" ] && gzip -t -c "$outputGzip" >/dev/null 2>/dev/null
                        return $?
                ;;
                create_gzip)
@@ -1103,7 +1138,7 @@ process_file_url() {
                append_newline "$R_TMP"
                [ -n "$cfg" ] && new_size="$(get_local_filesize "$R_TMP")"
                if [ -n "$new_size" ] && [ "$size" != "$new_size" ]; then
-                       uci set "${packageName}.${cfg}.size=$size"
+                       uci_set "$packageName" "$cfg" 'size' "$size"
                fi
                format="$(detect_file_type "$R_TMP")"
                case "$format" in
@@ -1223,9 +1258,9 @@ download_lists() {
        config_load "$packageName"
        config_foreach load_validate_file_url_section 'file_url' process_file_url_wrapper
        wait
-       if [ -n "$(uci changes "$packageName")" ]; then 
+       if [ -n "$(uci_changes "$packageName")" ]; then 
                output 2 "Saving updated file size(s) "
-               if uci commit "$packageName"; then output_okn; else output_failn; fi
+               if uci_commit "$packageName"; then output_okn; else output_failn; fi
        fi
        output 1 '\n'
 
@@ -1401,6 +1436,11 @@ $(sed '/^[[:space:]]*$/d' "$A_TMP")"
                output_failn
                json add error 'errorMovingDataFile'
        fi
+       case "$dns" in
+               unbound.adb_list)
+                       sed -i '1 i\server:' "$outputFile"
+               ;;
+       esac
        if [ "$compressed_cache" -gt 0 ]; then
                output 2 'Creating compressed cache '
                json set message "$(get_text 'statusProcessing'): creating compressed cache"
@@ -1571,22 +1611,7 @@ adb_check() {
                                output "Found $c matches for '$string' in '$outputFile'.\\n"
                        fi
                        if [ "$c" -le 20 ]; then
-                               case "$dns" in
-                                       dnsmasq.addnhosts)
-                                               grep "$string" "$outputFile" | sed 's|^127.0.0.1 ||;s|^:: ||;';;
-                                       dnsmasq.conf)
-                                               grep "$string" "$outputFile" | sed 's|local=/||;s|/$||;';;
-                                       dnsmasq.ipset)
-                                               grep "$string" "$outputFile" | sed 's|ipset=/||;s|/adb$||;';;
-                                       dnsmasq.nftset)
-                                               grep "$string" "$outputFile" | sed 's|nftset=/||;s|/4#inet#adb#adb4||;';;
-                                       dnsmasq.servers)
-                                               grep "$string" "$outputFile" | sed 's|server=/||;s|/$||;';;
-                                       smartdns.*)
-                                               grep "$string" "$outputFile";;
-                                       unbound.adb_list)
-                                               grep "$string" "$outputFile" | sed 's|^local-zone: "||;s|" static$||;';;
-                               esac
+                               grep "$string" "$outputFile" | sed "$outputOutputFilter"
                        fi
                else
                        output "The '$string' is not found in current block-list ('$outputFile').\\n"
@@ -1681,6 +1706,12 @@ adb_config_update() {
        return 0
 }
 
+adb_show_blocklist() {
+       local validation_result="$3"
+       load_environment "$validation_result" 'quiet' || return 1
+       sed "$outputOutputFilter" "$outputFile"
+}
+
 adb_sizes() {
        _config_add_url_size() {
                local cfg="$1" url size
@@ -1688,7 +1719,7 @@ adb_sizes() {
                size="$(get_url_filesize "$url")"
                output "$url${size:+: $size} "
                if [ -n "$size" ]; then
-                       uci set "${packageName}.${cfg}.size=$size"
+                       uci_set "$packageName" "$cfg" 'size' "$size"
                        output_okn
                else
                        output_failn
@@ -1699,12 +1730,12 @@ adb_sizes() {
        load_environment "$validation_result" 'quiet' || return 1
        config_load "$packageName"
        config_foreach _config_add_url_size 'file_url'
-       uci commit "$packageName"
+       uci_commit "$packageName"
 }
 
 # shellcheck disable=SC2120
 adb_start() {
-       local action status error message stats c
+       local action status error message stats c iface
        local param="$1" validation_result="$3"
 
        load_environment "$validation_result" "$param" || return 1
@@ -1716,7 +1747,7 @@ adb_start() {
        action="$(config_cache get 'trigger_service')"
        fw4_restart_flag="$(config_cache get 'trigger_fw4')"
 
-       if [ "$action" = 'on_boot' ] || [ "$param" = 'on_boot' ]; then
+       if [ "$action" = 'on_boot' ] || [ "$param" = 'on_boot' ] || [ "$param" = 'on_pause' ]; then
                if cache 'test_gzip' || cache 'test'; then
                        action='restore'
                else
@@ -1840,25 +1871,29 @@ adb_start() {
 # shellcheck disable=SC3060
                for c in ${force_dns_port/,/ }; do
                        if netstat -tuln | grep LISTEN | grep ":${c}" >/dev/null 2>&1; then
-                               json_add_object ""
-                               json_add_string type redirect
-                               json_add_string target DNAT
-                               json_add_string src lan
-                               json_add_string proto "tcp udp"
-                               json_add_string src_dport "$c"
-                               json_add_string dest_port "$c"
-                               json_add_string family any
-                               json_add_boolean reflection 0
-                               json_close_object
+                               for iface in $force_dns_interface; do
+                                       json_add_object ""
+                                       json_add_string type redirect
+                                       json_add_string target DNAT
+                                       json_add_string src "$iface"
+                                       json_add_string proto "tcp udp"
+                                       json_add_string src_dport "$c"
+                                       json_add_string dest_port "$c"
+                                       json_add_string family any
+                                       json_add_boolean reflection 0
+                                       json_close_object
+                               done
                        else
-                               json_add_object ""
-                               json_add_string type rule
-                               json_add_string src lan
-                               json_add_string dest "*"
-                               json_add_string proto "tcp udp"
-                               json_add_string dest_port "$c"
-                               json_add_string target REJECT
-                               json_close_object
+                               for iface in $force_dns_interface; do
+                                       json_add_object ""
+                                       json_add_string type rule
+                                       json_add_string src "$iface"
+                                       json_add_string dest "*"
+                                       json_add_string proto "tcp udp"
+                                       json_add_string dest_port "$c"
+                                       json_add_string target REJECT
+                                       json_close_object
+                               done
                        fi
                done
        fi
@@ -1870,14 +1905,16 @@ adb_start() {
                        json_add_string match dest_net
                        json_add_string storage hash
                        json_close_object
-                       json_add_object ""
-                       json_add_string type rule
-                       json_add_string ipset adb
-                       json_add_string src lan
-                       json_add_string dest "*"
-                       json_add_string proto "tcp udp"
-                       json_add_string target REJECT
-                       json_close_object
+                       for iface in $force_dns_interface; do
+                               json_add_object ""
+                               json_add_string type rule
+                               json_add_string ipset adb
+                               json_add_string src "$iface"
+                               json_add_string dest "*"
+                               json_add_string proto "tcp udp"
+                               json_add_string target REJECT
+                               json_close_object
+                       done
                ;;
                dnsmasq.nftset|smartdns.nftset)
                        json_add_object ""
@@ -1886,14 +1923,16 @@ adb_start() {
                        json_add_string family 4
                        json_add_string match dest_net
                        json_close_object
-                       json_add_object ""
-                       json_add_string type rule
-                       json_add_string ipset adb4
-                       json_add_string src lan
-                       json_add_string dest "*"
-                       json_add_string proto "tcp udp"
-                       json_add_string target REJECT
-                       json_close_object
+                       for iface in $force_dns_interface; do
+                               json_add_object ""
+                               json_add_string type rule
+                               json_add_string ipset adb4
+                               json_add_string src "$iface"
+                               json_add_string dest "*"
+                               json_add_string proto "tcp udp"
+                               json_add_string target REJECT
+                               json_close_object
+                       done
                        if [ "$ipv6_enabled" -ne '0' ]; then
                                json_add_object ""
                                json_add_string type ipset
@@ -1901,14 +1940,16 @@ adb_start() {
                                json_add_string family 6
                                json_add_string match dest_net
                                json_close_object
-                               json_add_object ""
-                               json_add_string type rule
-                               json_add_string ipset adb6
-                               json_add_string src lan
-                               json_add_string dest "*"
-                               json_add_string proto "tcp udp"
-                               json_add_string target REJECT
-                               json_close_object
+                               for iface in $force_dns_interface; do
+                                       json_add_object ""
+                                       json_add_string type rule
+                                       json_add_string ipset adb6
+                                       json_add_string src "$iface"
+                                       json_add_string dest "*"
+                                       json_add_string proto "tcp udp"
+                                       json_add_string target REJECT
+                                       json_close_object
+                               done
                        fi
                ;;
        esac
@@ -2027,6 +2068,7 @@ killcache() {
        resolver 'cleanup'
        return 0
 }
+show_blocklist() { load_validate_config 'config' adb_show_blocklist "'$*'"; }
 reload_service() { rc_procd start_service 'restart'; }
 restart_service() { rc_procd start_service 'restart'; }
 service_started() { is_fw4_restart_needed && procd_set_config_changed firewall; }
@@ -2069,6 +2111,7 @@ load_validate_file_url_section() {
 load_validate_config() {
        local enabled
        local force_dns
+       local force_dns_interface
        local force_dns_port
        local parallel_downloads
        local debug
@@ -2088,6 +2131,7 @@ load_validate_config() {
        local verbosity
        local procd_trigger_wan6
        local procd_boot_wan_timeout
+       local procd_lan_interface_name
        local led
        local dns
        local dnsmasq_instance
@@ -2097,6 +2141,7 @@ load_validate_config() {
        uci_load_validate "$packageName" "$packageName" "$1" "${2}${3:+ $3}" \
                'enabled:bool:0' \
                'force_dns:bool:1' \
+               'force_dns_interface:list(network):lan' \
                'force_dns_port:list(integer):53,853' \
                'parallel_downloads:bool:1' \
                'debug:bool:0' \
@@ -2119,6 +2164,7 @@ load_validate_config() {
                'led:or("", "none", file, device, string)' \
                'dns:or("dnsmasq.addnhosts", "dnsmasq.conf", "dnsmasq.ipset", "dnsmasq.nftset", "dnsmasq.servers", "smartdns.domainset", "smartdns.ipset", "smartdns.nftset", "unbound.adb_list"):dnsmasq.servers' \
                'dnsmasq_instance:list(or(integer, string)):*' \
+               'smartdns_instance:list(or(integer, string)):*' \
                'allowed_domain:list(string)' \
                'blocked_domain:list(string)' \
                'dnsmasq_config_file_url:string'