You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

894 lines
27 KiB

  1. #!/bin/sh /etc/rc.common
  2. PKG_VERSION=
  3. export START=94
  4. export USE_PROCD=1
  5. export LC_ALL=C
  6. export EXTRA_COMMANDS="check dl killcache status"
  7. export EXTRA_HELP=" check Checks if specified domain is found in current blacklist
  8. dl Force-redownloads all the list
  9. status Shows the service last-run status"
  10. readonly packageName="simple-adblock"
  11. readonly serviceName="$packageName $PKG_VERSION"
  12. readonly addnhostsFile="/var/run/${packageName}.addnhosts"
  13. readonly addnhostsCache="/var/run/${packageName}.addnhosts.cache"
  14. readonly addnhostsGzip="/etc/${packageName}.addnhosts.gz"
  15. readonly addnhostsOutputFilter='s|^|127.0.0.1 |;s|$||'
  16. readonly addnhostsOutputFilterIPv6='s|^|:: |;s|$||'
  17. readonly dnsmasqFile="/var/dnsmasq.d/${packageName}"
  18. readonly dnsmasqCache="/var/run/${packageName}.dnsmasq.cache"
  19. readonly dnsmasqGzip="/etc/${packageName}.dnsmasq.gz"
  20. readonly dnsmasqOutputFilter='s|^|local=/|;s|$|/|'
  21. readonly serversFile="/var/run/${packageName}.servers"
  22. readonly serversCache="/var/run/${packageName}.servers.cache"
  23. readonly serversGzip="/etc/${packageName}.servers.gz"
  24. readonly serversOutputFilter='s|^|server=/|;s|$|/|'
  25. readonly unboundFile="/var/lib/unbound/adb_list.${packageName}"
  26. readonly unboundCache="/var/run/${packageName}.unbound.cache"
  27. readonly unboundGzip="/etc/${packageName}.unbound.gz"
  28. readonly unboundOutputFilter='s|^|local-zone: "|;s|$|" static|'
  29. readonly A_TMP="/var/${packageName}.hosts.a.tmp"
  30. readonly B_TMP="/var/${packageName}.hosts.b.tmp"
  31. readonly PIDFile="/var/run/${packageName}.pid"
  32. readonly jsonFile="/var/run/${packageName}.json"
  33. 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;'
  34. readonly domainsFilter='/^#/d;s/[[:space:]]*#.*$//;s/[[:space:]]*$//;s/[[:cntrl:]]$//;/[[:space:]]/d;/[`~!@#\$%\^&\*()=+;:"'\'',<>?/\|[{}]/d;/]/d;/\./!d;/^$/d;/[^[:alnum:]_.-]/d;'
  35. readonly checkmark='\xe2\x9c\x93'
  36. readonly xmark='\xe2\x9c\x97'
  37. readonly _OK_='\033[0;32m\xe2\x9c\x93\033[0m'
  38. readonly _FAIL_='\033[0;31m\xe2\x9c\x97\033[0m'
  39. readonly __OK__='\033[0;32m[\xe2\x9c\x93]\033[0m'
  40. readonly __FAIL__='\033[0;31m[\xe2\x9c\x97]\033[0m'
  41. readonly _ERROR_='\033[0;31mERROR\033[0m'
  42. readonly statusSuccess='Success'
  43. readonly statusFail='Fail'
  44. readonly statusDownloading='Downloading'
  45. readonly statusReloading='Reloading'
  46. readonly statusRestarting='Restarting'
  47. readonly statusStarting='Starting'
  48. readonly statusForceReloading='Force-Reloading'
  49. readonly statusProcessing='Processing'
  50. readonly statusStopped='Stopped'
  51. export logmsg
  52. create_lock() { [ -e "$PIDFile" ] && return 1; touch "$PIDFile"; }
  53. remove_lock() { [ -e "$PIDFile" ] && rm -f "$PIDFile"; }
  54. trap remove_lock EXIT
  55. output_ok() { output 1 "$_OK_"; output 2 "$__OK__\\n"; }
  56. output_okn() { output 1 "$_OK_\\n"; output 2 "$__OK__\\n"; }
  57. output_fail() { output 1 "$_FAIL_\\n"; output 2 "$__FAIL__\\n"; }
  58. output_failn() { output 1 "$_FAIL_"; output 2 "$__FAIL__\\n"; }
  59. output() {
  60. # Can take a single parameter (text) to be output at any verbosity
  61. # Or target verbosity level and text to be output at specifc verbosity
  62. if [ $# -ne 1 ]; then
  63. if [ $((verbosity & $1)) -gt 0 ] || [ "$verbosity" == "$1" ]; then shift; else return 0; fi
  64. fi
  65. [ -t 1 ] && echo -e -n "$1"
  66. local msg=$(echo -n "${1/$serviceName /service }" | sed 's|\\033\[[0-9]\?;\?[0-9]\?[0-9]\?m||g');
  67. if [ "$(echo -e -n "$msg" | wc -l)" -gt 0 ]; then
  68. logger -t "${packageName:-service} [$$]" "$(echo -e -n "${logmsg}${msg}")"
  69. logmsg=""
  70. else
  71. logmsg="${logmsg}${msg}"
  72. fi
  73. }
  74. led_on(){ if [ -n "${1}" ] && [ -e "${1}/trigger" ]; then echo "default-on" > "${1}/trigger" 2>&1; fi; }
  75. led_off(){ if [ -n "${1}" ] && [ -e "${1}/trigger" ]; then echo "none" > "${1}/trigger" 2>&1; fi; }
  76. export serviceEnabled
  77. export forceDNS
  78. export parallelDL
  79. export debug
  80. export allowNonAscii
  81. export compressedCache
  82. export targetDNS
  83. export bootDelay
  84. export dlTimeout
  85. export curlRetry
  86. export verbosity
  87. export led
  88. export whitelist_domains
  89. export blacklist_domains
  90. export whitelist_domains_urls
  91. export blacklist_domains_urls
  92. export blacklist_hosts_urls
  93. export wan_if wan_gw wanphysdev dl_command serviceStatus dl_flag
  94. export outputFilter outputFilterIPv6 outputFile outputGzip outputCache ipv6Enabled
  95. load_package_config() {
  96. config_load "$packageName"
  97. config_get_bool serviceEnabled "config" "enabled" 1
  98. config_get_bool forceDNS "config" "force_dns" 1
  99. config_get_bool parallelDL "config" "parallel_downloads" 1
  100. config_get_bool debug "config" "debug" 0
  101. config_get_bool allowNonAscii "config" "allow_non_ascii" 0
  102. config_get_bool compressedCache "config" "compressed_cache" 0
  103. config_get_bool ipv6Enabled "config" "ipv6_enabled" 0
  104. config_get bootDelay "config" "boot_delay" "120"
  105. config_get dlTimeout "config" "download_timeout" "20"
  106. config_get curlRetry "config" "curl_retry" "3"
  107. config_get verbosity "config" "verbosity" "2"
  108. config_get led "config" "led"
  109. config_get targetDNS "config" "dns" "dnsmasq.servers"
  110. config_get whitelist_domains "config" "whitelist_domain"
  111. config_get blacklist_domains "config" "blacklist_domain"
  112. config_get whitelist_domains_urls "config" "whitelist_domains_url"
  113. config_get blacklist_domains_urls "config" "blacklist_domains_url"
  114. config_get blacklist_hosts_urls "config" "blacklist_hosts_url"
  115. if [ "$targetDNS" != "dnsmasq.addnhosts" ] && [ "$targetDNS" != "dnsmasq.conf" ] && \
  116. [ "$targetDNS" != "dnsmasq.servers" ] && [ "$targetDNS" != "unbound.adb_list" ]; then
  117. targetDNS="dnsmasq.servers"
  118. fi
  119. case "$targetDNS" in
  120. dnsmasq.addnhosts)
  121. outputFilter="$addnhostsOutputFilter"
  122. outputFile="$addnhostsFile"
  123. outputCache="$addnhostsCache"
  124. outputGzip="$addnhostsGzip"
  125. [ "$ipv6Enabled" -gt 0 ] && outputFilterIPv6="$addnhostsOutputFilterIPv6"
  126. rm -f "$dnsmasqFile" "$dnsmasqCache" "$dnsmasqGzip"
  127. rm -f "$serversFile" "$serversCache" "$serversGzip"
  128. rm -f "$unboundFile" "$unboundCache" "$unboundGzip"
  129. ;;
  130. dnsmasq.conf)
  131. outputFilter="$dnsmasqOutputFilter"
  132. outputFile="$dnsmasqFile"
  133. outputCache="$dnsmasqCache"
  134. outputGzip="$dnsmasqGzip"
  135. rm -f "$addnhostsFile" "$addnhostsCache" "$addnhostsGzip"
  136. rm -f "$serversFile" "$serversCache" "$serversGzip"
  137. rm -f "$unboundFile" "$unboundCache" "$unboundGzip"
  138. ;;
  139. dnsmasq.servers)
  140. outputFilter="$serversOutputFilter"
  141. outputFile="$serversFile"
  142. outputCache="$serversCache"
  143. outputGzip="$serversGzip"
  144. rm -f "$dnsmasqFile" "$dnsmasqCache" "$dnsmasqGzip"
  145. rm -f "$addnhostsFile" "$addnhostsCache" "$addnhostsGzip"
  146. rm -f "$unboundFile" "$unboundCache" "$unboundGzip"
  147. ;;
  148. unbound.adb_list)
  149. outputFilter="$unboundOutputFilter"
  150. outputFile="$unboundFile"
  151. outputCache="$unboundCache"
  152. outputGzip="$unboundGzip"
  153. rm -f "$dnsmasqFile" "$dnsmasqCache" "$dnsmasqGzip"
  154. rm -f "$addnhostsFile" "$addnhostsCache" "$addnhostsGzip"
  155. rm -f "$serversFile" "$serversCache" "$serversGzip"
  156. ;;
  157. esac
  158. if [ -z "${verbosity##*[!0-9]*}" ] || [ "$verbosity" -lt 0 ] || [ "$verbosity" -gt 2 ]; then
  159. verbosity=1
  160. fi
  161. . /lib/functions/network.sh
  162. . /usr/share/libubox/jshn.sh
  163. # Prefer curl because it supports the file: scheme.
  164. if [ -x /usr/bin/curl ] ; then
  165. dl_command="curl --insecure --retry $curlRetry --connect-timeout $dlTimeout --silent"
  166. dl_flag="-o"
  167. else
  168. dl_command="wget --no-check-certificate --timeout $dlTimeout -q"
  169. dl_flag="-O"
  170. fi
  171. led="${led:+/sys/class/leds/$led}"
  172. }
  173. is_enabled() {
  174. load_package_config
  175. if [ "$debug" -ne 0 ]; then
  176. exec 1>>/tmp/simple-adblock.log
  177. exec 2>&1
  178. set -x
  179. fi
  180. if [ "$serviceEnabled" -eq 0 ]; then
  181. case "$1" in
  182. on_start)
  183. output "$packageName is currently disabled.\\n"
  184. output "Run the following commands before starting service again:\\n"
  185. output "uci set ${packageName}.config.enabled='1'; uci commit $packageName;\\n"
  186. ;;
  187. esac
  188. return 1
  189. fi
  190. [ ! -d "${outputFile%/*}" ] && mkdir -p "${outputFile%/*}"
  191. [ ! -d "${outputCache%/*}" ] && mkdir -p "${outputFile%/*}"
  192. [ ! -d "${outputGzip%/*}" ] && mkdir -p "${outputFile%/*}"
  193. cacheOps 'testGzip' && return 0
  194. network_flush_cache; network_find_wan wan_if; network_get_gateway wan_gw "$wan_if";
  195. [ -n "$wan_gw" ] && return 0
  196. output "$_ERROR_: $serviceName failed to discover WAN gateway.\\n"; return 1;
  197. }
  198. dnsmasq_kill() { killall -q -HUP dnsmasq; }
  199. dnsmasq_restart() { /etc/init.d/dnsmasq restart >/dev/null 2>&1; }
  200. unbound_restart() { /etc/init.d/unbound restart >/dev/null 2>&1; }
  201. reload_resolver() {
  202. local param output_text
  203. case $1 in
  204. on_start)
  205. if [ ! -s "$outputFile" ]; then
  206. tmpfs set status "$statusFail"
  207. tmpfs add error "Error: Failed to create $outputFile file."
  208. output "$_ERROR_: $serviceName failed to create its data file!\\n"
  209. return 1
  210. fi
  211. case "$targetDNS" in
  212. dnsmasq.addnhosts)
  213. uci -q del_list dhcp.@dnsmasq[0].addnhosts="$addnhostsFile"
  214. uci add_list dhcp.@dnsmasq[0].addnhosts="$addnhostsFile"
  215. if [ -n "$(uci changes dhcp)" ]; then
  216. uci commit dhcp
  217. param=dnsmasq_restart
  218. output_text="Restarting DNSMASQ"
  219. else
  220. param=dnsmasq_kill
  221. output_text="Reloading DNSMASQ"
  222. fi
  223. ;;
  224. dnsmasq.conf)
  225. param=dnsmasq_restart
  226. output_text="Restarting DNSMASQ"
  227. ;;
  228. dnsmasq.servers)
  229. if [ "$(uci -q get dhcp.@dnsmasq[0].serversfile)" != "$serversFile" ]; then
  230. uci set dhcp.@dnsmasq[0].serversfile="$serversFile"
  231. uci commit dhcp
  232. param=dnsmasq_restart
  233. output_text="Restarting DNSMASQ"
  234. else
  235. param=dnsmasq_kill
  236. output_text="Reloading DNSMASQ"
  237. fi
  238. ;;
  239. unbound.adb_list)
  240. param=unbound_restart
  241. output_text="Restarting Unbound"
  242. ;;
  243. esac
  244. output 1 "$output_text "
  245. output 2 "$output_text "
  246. tmpfs set message "$output_text"
  247. if eval "$param"; then
  248. tmpfs set status "$statusSuccess"
  249. led_on "$led"
  250. output_okn
  251. else
  252. output_fail
  253. tmpfs set status "$statusFail"
  254. tmpfs add error "Error: $output_text error."
  255. output "$_ERROR_: $serviceName $output_text error!\\n"
  256. return 1
  257. fi
  258. ;;
  259. on_stop)
  260. cacheOps 'create'
  261. case "$targetDNS" in
  262. dnsmasq.addnhosts | dnsmasq.servers)
  263. if [ -n "$(uci changes dhcp)" ]; then
  264. uci -q commit dhcp
  265. param=dnsmasq_restart
  266. else
  267. param=dnsmasq_kill
  268. fi
  269. ;;
  270. dnsmasq.conf)
  271. param=dnsmasq_restart
  272. ;;
  273. unbound.adb_list)
  274. param=unbound_restart
  275. ;;
  276. esac
  277. eval "$param"
  278. return $?
  279. ;;
  280. quiet)
  281. case "$targetDNS" in
  282. dnsmasq.addnhosts | dnsmasq.servers | dnsmasq.conf)
  283. param=dnsmasq_restart
  284. ;;
  285. unbound.adb_list)
  286. param=unbound_restart
  287. ;;
  288. esac
  289. eval "$param"
  290. return $?
  291. ;;
  292. esac
  293. }
  294. tmpfs(){
  295. local action="$1" instance="$2" value="$3"
  296. local status message error stats
  297. local readReload readRestart curReload curRestart ret
  298. if [ -s "$jsonFile" ]; then
  299. status="$(jsonfilter -i $jsonFile -l1 -e "@['data']['status']")"
  300. message="$(jsonfilter -i $jsonFile -l1 -e "@['data']['message']")"
  301. error="$(jsonfilter -i $jsonFile -l1 -e "@['data']['error']")"
  302. stats="$(jsonfilter -i $jsonFile -l1 -e "@['data']['stats']")"
  303. readReload="$(jsonfilter -i $jsonFile -l1 -e "@['data']['reload']")"
  304. readRestart="$(jsonfilter -i $jsonFile -l1 -e "@['data']['restart']")"
  305. fi
  306. case "$action" in
  307. get)
  308. case "$instance" in
  309. status)
  310. echo "$status"; return;;
  311. message)
  312. echo "$message"; return;;
  313. error)
  314. echo "$error"; return;;
  315. stats)
  316. echo "$stats"; return;;
  317. triggers)
  318. curReload="$allowNonAscii $parallelDL $debug $dlTimeout $whitelist_domains $blacklist_domains $whitelist_domains_urls $blacklist_domains_urls $blacklist_hosts_urls $targetDNS"
  319. curRestart="$compressedCache $forceDNS $led"
  320. if [ "$curReload" != "$readReload" ]; then
  321. ret="download"
  322. elif [ "$curRestart" != "$readRestart" ]; then
  323. ret="restart"
  324. fi
  325. echo "$ret"
  326. return;;
  327. esac
  328. ;;
  329. add)
  330. case "$instance" in
  331. status)
  332. [ -n "$status" ] && status="$status $value" || status="$value";;
  333. message)
  334. [ -n "$message" ] && message="${message} ${value}" || message="$value";;
  335. error)
  336. [ -n "$error" ] && error="$error $value" || error="$value";;
  337. stats)
  338. [ -n "$stats" ] && stats="$stats $value" || stats="$value";;
  339. esac
  340. ;;
  341. del)
  342. case "$instance" in
  343. status)
  344. unset status;;
  345. message)
  346. unset message;;
  347. error)
  348. unset error;;
  349. stats)
  350. unset stats;;
  351. triggers)
  352. unset readReload; unset readRestart;;
  353. esac
  354. ;;
  355. set)
  356. case "$instance" in
  357. status)
  358. status="$value";;
  359. message)
  360. message="$value";;
  361. error)
  362. error="$value";;
  363. stats)
  364. stats="$value";;
  365. triggers)
  366. readReload="$allowNonAscii $parallelDL $debug $dlTimeout $whitelist_domains $blacklist_domains $whitelist_domains_urls $blacklist_domains_urls $blacklist_hosts_urls $targetDNS"
  367. readRestart="$compressedCache $forceDNS $led"
  368. ;;
  369. esac
  370. ;;
  371. esac
  372. json_init
  373. json_add_object "data"
  374. json_add_string version "$PKG_VERSION"
  375. json_add_string status "$status"
  376. json_add_string message "$message"
  377. json_add_string error "$error"
  378. json_add_string stats "$stats"
  379. json_add_string reload "$readReload"
  380. json_add_string restart "$readRestart"
  381. json_close_object
  382. json_dump > "$jsonFile"
  383. sync
  384. }
  385. cacheOps(){
  386. local R_TMP
  387. case "$1" in
  388. create|backup)
  389. [ -f "$outputFile" ] && mv "$outputFile" "$outputCache" >/dev/null 2>/dev/null
  390. return $?
  391. ;;
  392. restore|use)
  393. [ -f "$outputCache" ] && mv "$outputCache" "$outputFile" >/dev/null 2>/dev/null
  394. return $?
  395. ;;
  396. test)
  397. [ -s "$outputCache" ]
  398. return $?
  399. ;;
  400. testGzip)
  401. [ -s "$outputGzip" ] && gzip -t -c "$outputGzip"
  402. return $?
  403. ;;
  404. createGzip)
  405. R_TMP="$(mktemp -u -q -t ${packageName}_tmp.XXXXXXXX)"
  406. if gzip < "$outputFile" > "$R_TMP"; then
  407. if mv "$R_TMP" "$outputGzip"; then
  408. rm -f "$R_TMP"
  409. return 0
  410. else
  411. rm -f "$R_TMP"
  412. return 1
  413. fi
  414. else
  415. return 1
  416. fi
  417. ;;
  418. expand|unpack|expandGzip|unpackGzip)
  419. [ -s "$outputGzip" ] && gzip -dc < "$outputGzip" > "$outputCache"
  420. return $?
  421. ;;
  422. esac
  423. }
  424. is_chaos_calmer() { ubus -S call system board | grep -q "Chaos Calmer"; }
  425. remove_fw3_redirect() {
  426. local name
  427. config_get name "$1" "name"
  428. if [ -n "$name" ] && [ "$name" != "${name//simple_adblock}" ]; then
  429. uci -q del "firewall.$1"
  430. fi
  431. }
  432. fw3_setup() {
  433. config_load "firewall"
  434. config_foreach remove_fw3_redirect "redirect"
  435. if [ "$1" = "start" ]; then
  436. uci -q add firewall redirect >/dev/null 2>&1
  437. uci -q set firewall.@redirect[-1].name="simple_adblock_dns_hijack"
  438. uci -q set firewall.@redirect[-1].target="DNAT"
  439. uci -q set firewall.@redirect[-1].src="lan"
  440. uci -q set firewall.@redirect[-1].proto="tcpudp"
  441. uci -q set firewall.@redirect[-1].src_dport="53"
  442. uci -q set firewall.@redirect[-1].dest_port="53"
  443. uci -q set firewall.@redirect[-1].dest_ip="$ip"
  444. uci -q set firewall.@redirect[-1].reflection="0"
  445. fi
  446. if [ -n "$(uci changes firewall)" ]; then
  447. uci -q commit firewall
  448. /etc/init.d/firewall restart >/dev/null 2>&1
  449. fi
  450. }
  451. process_url() {
  452. local label type D_TMP R_TMP
  453. if [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ]; then return 1; fi
  454. label="${1##*//}"; label="${label%%/*}";
  455. if [ "$2" = "hosts" ]; then
  456. label="Hosts: $label"; filter="$hostsFilter";
  457. else
  458. label="Domains: $label"; filter="$domainsFilter";
  459. fi
  460. if [ "$3" = "blocked" ]; then
  461. type="Blocked"; D_TMP="$B_TMP";
  462. else
  463. type="Allowed"; D_TMP="$A_TMP";
  464. fi
  465. while [ -z "$R_TMP" ] || [ -e "$R_TMP" ]; do
  466. R_TMP="$(mktemp -u -q -t ${packageName}_tmp.XXXXXXXX)"
  467. done
  468. if ! $dl_command "$1" $dl_flag "$R_TMP" 2>/dev/null || [ ! -s "$R_TMP" ]; then
  469. output 1 "$_FAIL_"
  470. output 2 "[DL] $type $label $__FAIL__\\n"
  471. echo -e -n "Error: downloading '${1}'.\\n" >> "${jsonFile}.error"
  472. else
  473. sed -i "$filter" "$R_TMP"
  474. if [ ! -s "$R_TMP" ]; then
  475. output 1 "$_FAIL_"
  476. output 2 "[DL] $type $label $__FAIL__\\n"
  477. echo -e -n "Error: parsing '${1}'.\\n" >> "${jsonFile}.error"
  478. else
  479. cat "${R_TMP}" >> "$D_TMP"
  480. output 1 "$_OK_"
  481. output 2 "[DL] $type $label $__OK__\\n"
  482. fi
  483. fi
  484. rm -f "$R_TMP"
  485. return 0
  486. }
  487. download_lists() {
  488. local hf w_filter j=0 R_TMP
  489. tmpfs set message "${statusDownloading}..."
  490. rm -f "$A_TMP" "$B_TMP" "$outputFile" "$outputCache" "$outputGzip"
  491. if [ "$(awk '/^MemFree/ {print int($2/1000)}' "/proc/meminfo")" -lt 32 ]; then
  492. output 3 "Low free memory, restarting resolver... "
  493. if reload_resolver 'quiet'; then
  494. output_okn
  495. else
  496. output_fail
  497. fi
  498. fi
  499. touch $A_TMP; touch $B_TMP;
  500. output 1 "Downloading lists "
  501. rm -f "${jsonFile}.error"
  502. if [ -n "$blacklist_hosts_urls" ]; then
  503. for hf in ${blacklist_hosts_urls}; do
  504. if [ "$parallelDL" -gt 0 ]; then
  505. process_url "$hf" "hosts" "blocked" &
  506. else
  507. process_url "$hf" "hosts" "blocked"
  508. fi
  509. done
  510. fi
  511. if [ -n "$blacklist_domains_urls" ]; then
  512. for hf in ${blacklist_domains_urls}; do
  513. if [ "$parallelDL" -gt 0 ]; then
  514. process_url "$hf" "domains" "blocked" &
  515. else
  516. process_url "$hf" "domains" "blocked"
  517. fi
  518. done
  519. fi
  520. if [ -n "$whitelist_domains_urls" ]; then
  521. for hf in ${whitelist_domains_urls}; do
  522. if [ "$parallelDL" -gt 0 ]; then
  523. process_url "$hf" "domains" "allowed" &
  524. else
  525. process_url "$hf" "domains" "allowed"
  526. fi
  527. done
  528. fi
  529. wait
  530. [ -s "${jsonFile}.error" ] && tmpfs add error "$(cat "${jsonFile}.error")"
  531. rm -f "${jsonFile}.error"
  532. output 1 "\\n"
  533. [ -n "$blacklist_domains" ] && for hf in ${blacklist_domains}; do echo "$hf" | sed "$domainsFilter" >> $B_TMP; done
  534. whitelist_domains="${whitelist_domains}
  535. $(cat $A_TMP)"
  536. [ -n "$whitelist_domains" ] && for hf in ${whitelist_domains}; do hf=$(echo "$hf" | sed 's/\./\\./g'); w_filter="$w_filter/^${hf}$/d;/\\.${hf}$/d;"; done
  537. [ ! -s "$B_TMP" ] && return 1
  538. output 1 "Processing downloads "
  539. output 2 "Sorting combined list "
  540. tmpfs set message "$statusProcessing: sorting combined list"
  541. if [ "$allowNonAscii" -gt 0 ]; then
  542. if sort "$B_TMP" | uniq > "$A_TMP"; then
  543. output_ok
  544. else
  545. output_failn
  546. tmpfs add error "Error: Sorting error."
  547. fi
  548. else
  549. if sort "$B_TMP" | uniq | grep -E -v '[^a-zA-Z0-9=/.-]' > "$A_TMP"; then
  550. output_ok
  551. else
  552. output_failn
  553. tmpfs add error "Error: Sorting error."
  554. fi
  555. fi
  556. if [ "$targetDNS" == "dnsmasq.conf" ] || \
  557. [ "$targetDNS" == "dnsmasq.servers" ] || \
  558. [ "$targetDNS" == "unbound.adb_list" ]; then
  559. # TLD optimization written by Dirk Brenken (dev@brenken.org)
  560. output 2 "Optimizing combined list "
  561. tmpfs set message "$statusProcessing: optimizing combined list"
  562. if awk -F "." '{for(f=NF;f>1;f--)printf "%s.",$f;print $1}' "$A_TMP" > "$B_TMP"; then
  563. if sort "$B_TMP" > "$A_TMP"; then
  564. if awk '{if(NR==1){tld=$NF};while(getline){if($NF!~tld"\\."){print tld;tld=$NF}}print tld}' "$A_TMP" > "$B_TMP"; then
  565. if awk -F "." '{for(f=NF;f>1;f--)printf "%s.",$f;print $1}' "$B_TMP" > "$A_TMP"; then
  566. if sort "$A_TMP" | uniq > "$B_TMP"; then
  567. output_ok
  568. else
  569. output_failn
  570. tmpfs add error "Error: Data file optimization."
  571. mv "$A_TMP" "$B_TMP"
  572. fi
  573. else
  574. output_failn
  575. tmpfs add error "Error: Data file optimization."
  576. fi
  577. else
  578. output_failn
  579. tmpfs add error "Error: Data file optimization."
  580. mv "$A_TMP" "$B_TMP"
  581. fi
  582. else
  583. output_failn
  584. tmpfs add error "Error: Data file optimization."
  585. fi
  586. else
  587. output_failn
  588. tmpfs add error "Error: Data file optimization."
  589. mv "$A_TMP" "$B_TMP"
  590. fi
  591. else
  592. mv "$A_TMP" "$B_TMP"
  593. fi
  594. output 2 "Whitelisting domains "
  595. tmpfs set message "$statusProcessing: whitelisting domains"
  596. if sed -i "$w_filter" "$B_TMP"; then
  597. output_ok
  598. else
  599. output_failn
  600. tmpfs add error "Error: Whitelist processing."
  601. fi
  602. output 2 "Formatting merged file "
  603. tmpfs set message "$statusProcessing: formatting merged file"
  604. if [ -z "$outputFilterIPv6" ]; then
  605. if sed "$outputFilter" "$B_TMP" > "$A_TMP"; then
  606. output_ok
  607. else
  608. output_failn
  609. tmpfs add error "Error: Data file formatting."
  610. fi
  611. else
  612. if sed "$outputFilter" "$B_TMP" > "$A_TMP" && \
  613. sed "$outputFilterIPv6" "$B_TMP" >> "$A_TMP"; then
  614. output_ok
  615. else
  616. output_failn
  617. tmpfs add error "Error: Data file formatting."
  618. fi
  619. fi
  620. case "$targetDNS" in
  621. dnsmasq.addnhosts)
  622. output 2 "Creating DNSMASQ addnhosts file "
  623. tmpfs set message "$statusProcessing: creating DNSMASQ addnhosts file"
  624. ;;
  625. dnsmasq.conf)
  626. output 2 "Creating DNSMASQ config file "
  627. tmpfs set message "$statusProcessing: creating DNSMASQ config file"
  628. ;;
  629. dnsmasq.servers)
  630. output 2 "Creating DNSMASQ servers file "
  631. tmpfs set message "$statusProcessing: creating DNSMASQ servers file"
  632. ;;
  633. unbound.adb_list)
  634. output 2 "Creating Unbound adb_list file "
  635. tmpfs set message "$statusProcessing: creating Unbound adb_list file"
  636. ;;
  637. esac
  638. if mv "$A_TMP" "$outputFile"; then
  639. output_ok
  640. else
  641. output_failn
  642. tmpfs add error "Error: moving data file '${A_TMP}' to '${outputFile}'."
  643. fi
  644. if [ "$compressedCache" -gt 0 ]; then
  645. output 2 "Creating compressed cache "
  646. tmpfs set message "$statusProcessing: creating compressed cache"
  647. if cacheOps 'createGzip'; then
  648. output_ok
  649. else
  650. output_failn
  651. tmpfs add error "Error: creating compressed cache."
  652. fi
  653. else
  654. rm -f "$outputGzip"
  655. fi
  656. output 2 "Removing temporary files "
  657. tmpfs set message "$statusProcessing: removing temporary files"
  658. rm -f "/tmp/${packageName}_tmp.*" "$A_TMP" "$B_TMP" "$outputCache" || j=1
  659. if [ $j -eq 0 ]; then
  660. output_ok
  661. else
  662. output_failn
  663. tmpfs add error "Error: removing temporary files."
  664. fi
  665. output 1 "\\n"
  666. }
  667. boot() {
  668. load_package_config
  669. if create_lock; then
  670. sleep "$bootDelay"
  671. remove_lock
  672. rc_procd start_service && rc_procd service_triggers
  673. fi
  674. }
  675. start_service() {
  676. is_enabled 'on_start' || return 1
  677. local ip status error action
  678. if create_lock; then
  679. procd_open_instance "main"
  680. procd_set_param command /bin/true
  681. procd_set_param stdout 1
  682. procd_set_param stderr 1
  683. network_get_ipaddr ip "lan"
  684. if [ "$forceDNS" -ne 0 ] && [ -n "$ip" ]; then
  685. if is_chaos_calmer; then
  686. fw3_setup "start"
  687. else
  688. procd_open_data
  689. json_add_array firewall
  690. json_add_object ""
  691. json_add_string type redirect
  692. json_add_string target "DNAT"
  693. json_add_string src "lan"
  694. json_add_string dest "lan"
  695. json_add_string proto "tcpudp"
  696. json_add_string src_dport "53"
  697. json_add_string dest_port "53"
  698. json_add_string dest_ip "$ip"
  699. json_add_string name "simple-adblock-dns-hijack"
  700. json_add_string reflection "0"
  701. json_close_object
  702. json_close_array
  703. procd_close_data
  704. fi
  705. fi
  706. procd_close_instance
  707. status="$(tmpfs get status)"
  708. error="$(tmpfs get error)"
  709. action="$(tmpfs get triggers)"
  710. tmpfs set triggers
  711. tmpfs del status
  712. tmpfs del message
  713. tmpfs del error
  714. tmpfs del stats
  715. case "$1" in
  716. download) action="download";;
  717. restart|*)
  718. if [ ! -s "$outputFile" ] && ! cacheOps 'test' && ! cacheOps 'testGzip'; then
  719. action="download"
  720. elif cacheOps 'test' || cacheOps 'testGzip'; then
  721. action="start"
  722. fi
  723. if [ -n "$error" ]; then
  724. action="download"
  725. fi
  726. action="${action:-$1}"
  727. ;;
  728. esac
  729. case $action in
  730. download)
  731. if [ -s "$outputFile" ] || cacheOps 'test' || cacheOps 'testGzip'; then
  732. output 0 "Force-reloading $serviceName... "
  733. output 3 "Force-reloading $serviceName...\\n"
  734. tmpfs set status "$statusForceReloading"
  735. else
  736. output 0 "Starting $serviceName... "
  737. output 3 "Starting $serviceName...\\n"
  738. tmpfs set status "$statusStarting"
  739. fi
  740. download_lists
  741. reload_resolver 'on_start'
  742. ;;
  743. restart|start)
  744. if [ "$action" == "restart" ]; then
  745. output 0 "Restarting $serviceName... "
  746. output 3 "Restarting $serviceName...\\n"
  747. tmpfs set status "$statusRestarting"
  748. else
  749. output 0 "Starting $serviceName... "
  750. output 3 "Starting $serviceName...\\n"
  751. tmpfs set status "$statusStarting"
  752. fi
  753. if cacheOps 'testGzip' && ! cacheOps 'test' && [ ! -s "$outputFile" ]; then
  754. output 3 "Found compressed cache file, unpacking it "
  755. tmpfs set message "found compressed cache file, unpacking it."
  756. if cacheOps 'unpackGzip'; then
  757. output_okn
  758. else
  759. output_fail
  760. output "$_ERROR_: $serviceName failed to unpack compressed cache!\\n"
  761. tmpfs add error "Error: Failed to unpack compressed cache."
  762. return 1
  763. fi
  764. fi
  765. if cacheOps 'test' && [ ! -s "$outputFile" ]; then
  766. output 3 "Found cache file, reusing it "
  767. tmpfs set message "found cache file, reusing it."
  768. if cacheOps 'restore'; then
  769. output_okn
  770. else
  771. output_fail
  772. tmpfs add error "Error: moving '$outputCache' to '$outputFile'."
  773. fi
  774. fi
  775. reload_resolver 'on_start'
  776. ;;
  777. esac
  778. if [ -s "$outputFile" ] && [ "$(tmpfs get status)" != "$statusFail" ]; then
  779. output 0 "$__OK__\\n";
  780. local c="$(wc -l < "$outputFile")"
  781. output 3 "$serviceName is blocking $c domains "; output_okn
  782. tmpfs del message
  783. tmpfs set status "$statusSuccess: $c domains blocked (with ${targetDNS})."
  784. error="$(tmpfs get error)"
  785. if [ -n "$error" ]; then
  786. output "${error/Error:/$_ERROR_:}\\n"
  787. fi
  788. else
  789. output 0 "$__FAIL__\\n";
  790. tmpfs set status "$statusFail"
  791. tmpfs add error "Error: Failed to create blocklist."
  792. fi
  793. remove_lock
  794. else
  795. output 3 "$serviceName: another instance is starting up "; output_fail
  796. return 0
  797. fi
  798. }
  799. service_started() { procd_set_config_changed firewall; }
  800. service_stopped() { procd_set_config_changed firewall; }
  801. restart_service() { rc_procd start_service "restart"; }
  802. reload_service() { restart_service; }
  803. restart() { restart_service; }
  804. reload() { restart_service; }
  805. dl() { rc_procd start_service "download"; }
  806. killcache() {
  807. rm -f "$addnhostsCache" "$addnhostsGzip"
  808. rm -f "$dnsmasqCache" "$dnsmasqGzip"
  809. rm -f "$serversCache" "$serversGzip"
  810. rm -f "$unboundCache" "$unboundGzip"
  811. return 0
  812. }
  813. status() {
  814. local status="$(tmpfs get status)" error="$(tmpfs get error)" message="$(tmpfs get message)"
  815. if [ -n "$status" ] && [ -n "$message" ]; then
  816. status="${status}: $message"
  817. fi
  818. [ -n "$status" ] && output "$serviceName $status\\n"
  819. [ -n "$error" ] && output "$error\\n"
  820. }
  821. stop_service() {
  822. load_package_config
  823. if is_chaos_calmer; then
  824. fw3_setup 'stop'
  825. fi
  826. if [ -s "$outputFile" ]; then
  827. output "Stopping $serviceName... "
  828. tmpfs del triggers
  829. if reload_resolver 'on_stop'; then
  830. led_off "$led"
  831. output 0 "$__OK__\\n"; output_okn
  832. tmpfs set status "$statusStopped"
  833. tmpfs del message
  834. else
  835. output 0 "$__FAIL__\\n"; output_fail
  836. tmpfs set status "$statusFail"
  837. tmpfs add error "Error: error stopping $serviceName."
  838. output "$_ERROR_: error stopping $serviceName!\\n"
  839. fi
  840. fi
  841. }
  842. check() {
  843. load_package_config
  844. local string="$1"
  845. if [ ! -f "$outputFile" ]; then
  846. echo "No local blacklist ('$outputFile') found."
  847. elif [ -z "$string" ]; then
  848. echo "Usage: /etc/init.d/${packageName} check domain"
  849. elif grep -m1 -q "$string" "$outputFile"; then
  850. echo "Found $(grep -c "$string" "$outputFile") matches for '$string' in '$outputFile':"
  851. # grep "$string" "$outputFile" | sed 's|local=/||;s|/$||;'
  852. grep "$string" "$outputFile"
  853. else
  854. echo "The $string is not found in current blacklist ('$outputFile')."
  855. fi
  856. }