From 0539bf393c484d7d2e5b60c1881dd8cd5b49931c Mon Sep 17 00:00:00 2001 From: Stan Grishin Date: Thu, 31 Oct 2024 01:57:37 +0000 Subject: [PATCH] adblock-fast: update to 1.1.2-10 * bump compat version to accommodate new strings * improve the output() function (thanks @bigsmile74) * implement support for user-configurable per-instance dnsmasq confdirs for dnsmasq.conf|dnsmasq.ipset|dnsmasq.nftset options Signed-off-by: Stan Grishin --- net/adblock-fast/Makefile | 2 +- .../files/etc/init.d/adblock-fast | 251 +++++++++++++----- 2 files changed, 190 insertions(+), 63 deletions(-) diff --git a/net/adblock-fast/Makefile b/net/adblock-fast/Makefile index 59da8c48363a00..2b4f30aea16a19 100644 --- a/net/adblock-fast/Makefile +++ b/net/adblock-fast/Makefile @@ -6,7 +6,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=adblock-fast PKG_VERSION:=1.1.2 -PKG_RELEASE:=8 +PKG_RELEASE:=10 PKG_MAINTAINER:=Stan Grishin PKG_LICENSE:=AGPL-3.0-or-later diff --git a/net/adblock-fast/files/etc/init.d/adblock-fast b/net/adblock-fast/files/etc/init.d/adblock-fast index 7e706071eb75f6..280fa45a2d42cc 100755 --- a/net/adblock-fast/files/etc/init.d/adblock-fast +++ b/net/adblock-fast/files/etc/init.d/adblock-fast @@ -24,7 +24,7 @@ fi readonly packageName='adblock-fast' readonly PKG_VERSION='dev-test' -readonly packageCompat='2' +readonly packageCompat='3' readonly serviceName="$packageName $PKG_VERSION" readonly packageConfigFile="/etc/config/${packageName}" readonly dnsmasqAddnhostsFile="/var/run/${packageName}/dnsmasq.addnhosts" @@ -33,17 +33,17 @@ 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 dnsmasqConfFile="${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 dnsmasqIpsetFile="${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 dnsmasqNftsetFile="${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|' @@ -115,6 +115,7 @@ outputBlockedCountFilter= outputFilter= outputFilterIPv6= outputFile= +outputDnsmasqFileList= outputGzip= outputCache= outputOutputFilter= @@ -317,6 +318,7 @@ dns_set_output_values() { outputOutputFilter="$unboundOutputFilter" ;; esac + resolver 'on_load' } dnsmasq_hup() { killall -q -s HUP dnsmasq; } dnsmasq_kill() { killall -q -s KILL dnsmasq; } @@ -377,11 +379,13 @@ 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"; } +str_first_word() { echo "${1%% *}"; } # shellcheck disable=SC2018,SC2019 str_to_lower() { echo "$1" | tr 'A-Z' 'a-z'; } # shellcheck disable=SC2018,SC2019 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"; } +# shellcheck disable=SC3060 +str_replace() { echo "${1//$2/$3}"; } 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'; } @@ -459,29 +463,18 @@ get_url_filesize() { echo -en "$size" } -output() { -# Target verbosity level with the first parameter being an integer - is_integer() { case "$1" in ''|*[!0-9]*) return 1;; esac; } - local msg memmsg logmsg text - local sharedMemoryOutput="/dev/shm/$packageName-output" - if [ -z "$verbosity" ] && [ -n "$packageName" ]; then - verbosity="$(uci_get "$packageName" 'config' 'verbosity' '2')" - fi - if [ $# -ne 1 ] && is_integer "$1"; then - if [ $((verbosity & $1)) -gt 0 ] || [ "$verbosity" = "$1" ]; then shift; text="$*"; else return 0; fi - fi - text="${text:-$*}"; - [ -t 1 ] && printf "%b" "$text" # shellcheck disable=SC3060 - msg="${text//$serviceName /service }"; - if [ "$(printf "%b" "$msg" | wc -l)" -gt 0 ]; then - [ -s "$sharedMemoryOutput" ] && memmsg="$(cat "$sharedMemoryOutput")" - logmsg="$(printf "%b" "${memmsg}${msg}" | sed 's/\x1b\[[0-9;]*m//g')" - logger -t "${packageName:-service} [$$]" "$(printf "%b" "$logmsg")" - rm -f "$sharedMemoryOutput" - else - printf "%b" "$msg" >> "$sharedMemoryOutput" - fi +output() { + local v="${verbosity:-1}" + [ "$#" -ne '1' ] && { + case "$1" in [0-9]) [ $((v & $1)) -gt 0 ] && shift || return 0;; esac } + local msg="$*" queue="/dev/shm/$packageName-output" + [ -t 1 ] && printf "%b" "$msg" + [ "$msg" != "${msg//\\n}" ] && { + [ -s "$queue" ] && msg="$(cat "$queue")${msg}" && rm -f "$queue" + msg="$(printf "%b" "$msg" | sed 's/\x1b\[[0-9;]*m//g')" + logger -t "$packageName [$$]" "$(printf "%b" "$msg")" + } || printf "%b" "$msg" >> "$queue" } uci_add_list_if_new() { @@ -520,14 +513,15 @@ get_text() { errorNoNft) r="dnsmasq nft sets support is enabled in $packageName, but nft is not installed";; errorNoWanGateway) r="The ${serviceName} failed to discover WAN gateway";; errorOutputDirCreate) r="failed to create directory for %s file";; - errorOutputFileCreate) r="failed to create $outputFile file";; + errorOutputFileCreate) r="failed to create %s file";; errorFailDNSReload) r="failed to restart/reload DNS resolver";; errorSharedMemory) r="failed to access shared memory";; errorSorting) r="failed to sort data file";; errorOptimization) r="failed to optimize data file";; errorAllowListProcessing) r="failed to process allow-list";; errorDataFileFormatting) r="failed to format data file";; - errorMovingDataFile) r="failed to move data file '${A_TMP}' to '${outputFile}'";; + errorCopyingDataFile) r="failed to copy data file to '%s'";; + errorMovingDataFile) r="failed to move data file to '%s'";; errorCreatingCompressedCache) r="failed to create compressed cache";; errorRemovingTempFiles) r="failed to remove temporary files";; errorRestoreCompressedCache) r="failed to unpack compressed cache";; @@ -544,6 +538,10 @@ get_text() { errorDetectingFileType) r="failed to detect format";; errorNothingToDo) r="no blocked list URLs nor blocked-domains enabled";; errorTooLittleRam) r="free ram (%s) is not enough to process all enabled block-lists";; + errorCreatingBackupFile) r="failed to create backup file %s";; + errorDeletingDataFile) r="failed to delete data file %s";; + errorRestoringBackupFile) r="failed to restore backup file %s";; + errorNoOutputFile) r="failed to create final block-list %s";; statusNoInstall) r="$serviceName is not installed or not found";; statusStopped) r="Stopped";; @@ -560,6 +558,7 @@ get_text() { warningMissingRecommendedPackages) r="some recommended packages are missing";; warningInvalidCompressedCacheDir) r="invalid compressed cache directory '%s'";; warningFreeRamCheckFail) r="can't detect free RAM";; + *) r="Unknown text '$1'";; esac shift # shellcheck disable=SC2059 @@ -834,7 +833,7 @@ load_environment() { config_load "$packageName" config_foreach append_url 'file_url' load_environment_flag=1 - cache 'test' && return 0 + cache 'test' && return 0 cache 'test_gzip' && return 0 if [ "$param" = 'on_boot' ]; then load_network "$param" @@ -846,7 +845,7 @@ load_environment() { resolver() { _dnsmasq_instance_config() { - local cfg="$1" param="$2" + local cfg="$1" param="$2" confdir confdirFile [ -s "/etc/config/dhcp" ] || return 0 case "$param" in dnsmasq.addnhosts) @@ -855,7 +854,13 @@ resolver() { fi uci_add_list_if_new 'dhcp' "$cfg" 'addnhosts' "$dnsmasqAddnhostsFile" ;; - cleanup|dnsmasq.conf|dnsmasq.ipset|dnsmasq.nftset|unbound.adb_list) + cleanup|unbound.adb_list) + uci_remove_list 'dhcp' "$cfg" 'addnhosts' "$dnsmasqAddnhostsFile" + if [ "$(uci_get 'dhcp' "$cfg" 'serversfile')" = "$dnsmasqServersFile" ]; then + uci_remove 'dhcp' "$cfg" 'serversfile' + fi + ;; + dnsmasq.conf|dnsmasq.ipset|dnsmasq.nftset) uci_remove_list 'dhcp' "$cfg" 'addnhosts' "$dnsmasqAddnhostsFile" if [ "$(uci_get 'dhcp' "$cfg" 'serversfile')" = "$dnsmasqServersFile" ]; then uci_remove 'dhcp' "$cfg" 'serversfile' @@ -869,6 +874,20 @@ resolver() { ;; esac } +# shellcheck disable=SC2317 + _dnsmasq_instance_init() { + local cfg="$1" param="$2" confdir confdirFile + [ -s "/etc/config/dhcp" ] || return 0 + case "$param" in + dnsmasq.conf|dnsmasq.ipset|dnsmasq.nftset) + config_get confdir "$cfg" 'confdir' '/tmp/dnsmasq.d' + confdirFile="${confdir}/${outputFile}" + if ! str_contains "$dnsmasqFileList" "$confdirFile"; then + dnsmasqFileList="${dnsmasqFileList:+$dnsmasqFileList }${confdirFile}" + fi + ;; + esac + } _smartdns_instance_config() { [ -s "/etc/config/smartdns" ] || return 0 local cfg="$1" param="$2" @@ -920,14 +939,29 @@ resolver() { [ -n "$(uci_changes 'smartdns')" ] && uci_commit 'smartdns' fi ;; + on_load) + case "$dns" in + dnsmasq.conf|dnsmasq.ipset|dnsmasq.nftset) + [ -z "$dnsmasqFileList" ] || return 0 + config_load 'dhcp' + if [ "$dnsmasq_instance" = "*" ]; then + config_foreach _dnsmasq_instance_init 'dnsmasq' "$dns" + elif [ -n "$dnsmasq_instance" ]; then + for i in $dnsmasq_instance; do + _dnsmasq_instance_init "@dnsmasq[$i]" "$dns" || _dnsmasq_instance_init "$i" "$dns" + done + fi + outputFile="$(str_first_word "$dnsmasqFileList")" + ;; + esac + ;; on_start) if [ ! -s "$outputFile" ]; then json set status 'statusFail' - json add error 'errorOutputFileCreate' - output "${_ERROR_}: $(get_text 'errorOutputFileCreate')!\n" + json add error 'errorOutputFileCreate' "$outputFile" + output "${_ERROR_}: $(get_text 'errorOutputFileCreate' "$outputFile")!\n" return 1 fi - config_load 'dhcp' if [ "$dnsmasq_instance" = "*" ]; then config_foreach _dnsmasq_instance_config 'dnsmasq' "$dns" @@ -947,8 +981,21 @@ resolver() { case "$dns" in dnsmasq.*) - chmod 660 "$outputFile" - chown root:dnsmasq "$outputFile" >/dev/null 2>/dev/null + if [ -n "$dnsmasqFileList" ]; then + local i + for i in $dnsmasqFileList; do + chmod 660 "$i" + chown root:dnsmasq "$i" >/dev/null 2>/dev/null + done + elif [ -s "$outputFile" ]; then + chmod 660 "$outputFile" + chown root:dnsmasq "$outputFile" >/dev/null 2>/dev/null + else + json set status 'statusFail' + json add error 'errorNoOutputFile' "$outputFile" + output "${_ERROR_}: $(get_text 'errorNoOutputFile' "$outputFile")!\n" + return 1 + fi param='dnsmasq_restart' output_text='Restarting dnsmasq' ;; @@ -1040,12 +1087,44 @@ cache() { local R_TMP case "$1" in create|backup) - [ -s "$outputFile" ] && { mv -f "$outputFile" "$outputCache"; } >/dev/null 2>/dev/null - return $? + if [ -n "$dnsmasqFileList" ]; then + local i __firstFile + for i in $dnsmasqFileList; do + if [ -z "$__firstFile" ]; then + __firstFile="$i" + if ! mv "$i" "$outputCache"; then + json add error 'errorCreatingBackupFile' "$outputCache" + fi + else + if ! rm -f "$i"; then + json add error 'errorDeletingDataFile' "$i" + fi + fi + done + else + [ -s "$outputFile" ] && { mv -f "$outputFile" "$outputCache"; } >/dev/null 2>/dev/null + return $? + fi ;; restore|use) - [ -s "$outputCache" ] && mv "$outputCache" "$outputFile" >/dev/null 2>/dev/null - return $? + if [ -n "$dnsmasqFileList" ]; then + local i __firstFile + for i in $dnsmasqFileList; do + if [ -z "$__firstFile" ]; then + __firstFile="$i" + if ! mv "$outputCache" "$i"; then + json add error 'errorRestoringBackupFile' "$i" + fi + else + if ! cp "$__firstFile" "$i"; then + json add error 'errorRestoringBackupFile' "$i" + fi + fi + done + else + [ -s "$outputCache" ] && mv "$outputCache" "$outputFile" >/dev/null 2>/dev/null + return $? + fi ;; test) [ -s "$outputCache" ] @@ -1191,12 +1270,25 @@ download_dnsmasq_file() { rm -f "$runningErrorFile" fi output 2 'Moving dnsmasq file ' - if mv "$B_TMP" "$outputFile"; then - output 2 "$__OK__\n" + local i __firstFile + for i in $dnsmasqFileList; do + if [ -z "$__firstFile" ]; then + __firstFile="$i" + if mv "$B_TMP" "$i"; then + output 2 "$__OK__\n" + else + output 2 "$__FAIL__\n" + json add error 'errorMovingDataFile' "$i" + fi else - output 2 "$__FAIL__\n" - json add error 'errorMovingDataFile' + if cp "$__firstFile" "$i"; then + output 2 "$__OK__\n" + else + output 2 "$__FAIL__\n" + json add error 'errorCopyingDataFile' "$i" + fi fi + done output 1 '\n' } @@ -1417,15 +1509,15 @@ $(sed '/^[[:space:]]*$/d' "$A_TMP")" json set message "$(get_text 'statusProcessing'): creating dnsmasq addnhosts file" ;; dnsmasq.conf) - output 2 'Creating dnsmasq config file ' + output 2 'Creating dnsmasq config file(s) ' json set message "$(get_text 'statusProcessing'): creating dnsmasq config file" ;; dnsmasq.ipset) - output 2 'Creating dnsmasq ipset file ' + output 2 'Creating dnsmasq ipset file(s) ' json set message "$(get_text 'statusProcessing'): creating dnsmasq ipset file" ;; dnsmasq.nftset) - output 2 'Creating dnsmasq nft set file ' + output 2 'Creating dnsmasq nft set file(s) ' json set message "$(get_text 'statusProcessing'): creating dnsmasq nft set file" ;; dnsmasq.servers) @@ -1450,16 +1542,45 @@ $(sed '/^[[:space:]]*$/d' "$A_TMP")" ;; esac - if mv "$B_TMP" "$outputFile"; then - output_ok - else - output_failn - json add error 'errorMovingDataFile' - fi case "$dns" in + dnsmasq.conf|dnsmasq.ipset|dnsmasq.nftset) + local i __firstFile + for i in $dnsmasqFileList; do + if [ -z "$__firstFile" ]; then + __firstFile="$i" + if mv "$B_TMP" "$i"; then + output 2 "$__OK__\n" + else + output 2 "$__FAIL__\n" + json add error 'errorMovingDataFile' "$i" + fi + else + if cp "$__firstFile" "$i"; then + output 2 "$__OK__\n" + else + output 2 "$__FAIL__\n" + json add error 'errorCopyingDataFile' "$i" + fi + fi + done + ;; unbound.adb_list) + if mv "$B_TMP" "$outputFile"; then + output_ok + else + output_failn + json add error 'errorMovingDataFile' "$outputFile" + fi sed -i '1 i\server:' "$outputFile" ;; + *) + if mv "$B_TMP" "$outputFile"; then + output_ok + else + output_failn + json add error 'errorMovingDataFile' "$outputFile" + fi + ;; esac if [ "$compressed_cache" -gt 0 ]; then output 2 'Creating compressed cache ' @@ -1506,20 +1627,26 @@ adb_allow() { for c in $string; do output 2 " $c " hf="$(echo "$c" | sed 's/\./\\./g')" - if sed -i "\:\(/\|\.\)${hf}/:d" "$outputFile" && \ - uci_add_list_if_new "${packageName}" 'config' 'allowed_domain' "$c"; then - output_ok - else - output_fail - fi + local f + for f in ${dnsmasqFileList:-$outputFile}; do + if sed -i "\:\(/\|\.\)${hf}/:d" "$f"; then + output_ok + else + output_fail + fi + done if [ -n "$outputAllowFilter" ]; then - if echo "$c" | sed -E "$outputAllowFilter" >> "$outputFile" && \ - uci_add_list_if_new "${packageName}" 'config' 'allowed_domain' "$c"; then + if echo "$c" | sed -E "$outputAllowFilter" >> "$outputFile"; then output_ok else output_fail fi fi + if uci_add_list_if_new "${packageName}" 'config' 'allowed_domain' "$c"; then + output_ok + else + output_fail + fi done if [ "$compressed_cache" -gt 0 ]; then output 2 'Creating compressed cache '