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.

1275 lines
34 KiB

  1. #!/bin/sh
  2. # dns based ad/abuse domain blocking
  3. # written by Dirk Brenken (dev@brenken.org)
  4. # This is free software, licensed under the GNU General Public License v3.
  5. # You should have received a copy of the GNU General Public License
  6. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  7. # set initial defaults
  8. #
  9. LC_ALL=C
  10. PATH="/usr/sbin:/usr/bin:/sbin:/bin"
  11. adb_ver="3.6.1"
  12. adb_sysver="unknown"
  13. adb_enabled=0
  14. adb_debug=0
  15. adb_backup_mode=0
  16. adb_forcesrt=0
  17. adb_forcedns=0
  18. adb_jail=0
  19. adb_maxqueue=8
  20. adb_notify=0
  21. adb_notifycnt=0
  22. adb_triggerdelay=0
  23. adb_backup=0
  24. adb_backupdir="/mnt"
  25. adb_fetchutil="uclient-fetch"
  26. adb_dns="dnsmasq"
  27. adb_dnsprefix="adb_list"
  28. adb_dnsfile="${adb_dnsprefix}.overall"
  29. adb_dnsjail="${adb_dnsprefix}.jail"
  30. adb_dnsflush=0
  31. adb_whitelist="/etc/adblock/adblock.whitelist"
  32. adb_rtfile="/tmp/adb_runtime.json"
  33. adb_hashutil="$(command -v sha256sum)"
  34. adb_hashold=""
  35. adb_hashnew=""
  36. adb_report=0
  37. adb_repiface="br-lan"
  38. adb_replisten="53"
  39. adb_repdir="/tmp"
  40. adb_reputil="$(command -v tcpdump)"
  41. adb_repchunkcnt="5"
  42. adb_repchunksize="1"
  43. adb_cnt=""
  44. adb_rc=0
  45. adb_action="${1:-"start"}"
  46. adb_pidfile="/var/run/adblock.pid"
  47. # load adblock environment
  48. #
  49. f_envload()
  50. {
  51. local dns_up sys_call sys_desc sys_model sys_ver cnt=0
  52. # get system information
  53. #
  54. sys_call="$(ubus -S call system board 2>/dev/null)"
  55. if [ -n "${sys_call}" ]
  56. then
  57. sys_desc="$(printf '%s' "${sys_call}" | jsonfilter -e '@.release.description')"
  58. sys_model="$(printf '%s' "${sys_call}" | jsonfilter -e '@.model')"
  59. sys_ver="$(cat /etc/turris-version 2>/dev/null)"
  60. if [ -n "${sys_ver}" ]
  61. then
  62. sys_desc="${sys_desc}/${sys_ver}"
  63. fi
  64. adb_sysver="${sys_model}, ${sys_desc}"
  65. fi
  66. # check hash utility
  67. #
  68. if [ ! -x "${adb_hashutil}" ]
  69. then
  70. adb_hashutil="$(command -v md5sum)"
  71. fi
  72. # parse 'global' and 'extra' section by callback
  73. #
  74. config_cb()
  75. {
  76. local type="${1}"
  77. if [ "${type}" = "adblock" ]
  78. then
  79. option_cb()
  80. {
  81. local option="${1}"
  82. local value="${2}"
  83. eval "${option}=\"${value}\""
  84. }
  85. else
  86. reset_cb
  87. fi
  88. }
  89. # parse 'source' typed sections
  90. #
  91. parse_config()
  92. {
  93. local value opt section="${1}" options="enabled adb_src adb_src_rset adb_src_cat"
  94. eval "adb_sources=\"${adb_sources} ${section}\""
  95. for opt in ${options}
  96. do
  97. config_get value "${section}" "${opt}"
  98. if [ -n "${value}" ]
  99. then
  100. eval "${opt}_${section}=\"${value}\""
  101. fi
  102. done
  103. }
  104. # load adblock config
  105. #
  106. config_load adblock
  107. config_foreach parse_config source
  108. # check dns backend
  109. #
  110. case "${adb_dns}" in
  111. dnsmasq)
  112. adb_dnsinstance="${adb_dnsinstance:-"0"}"
  113. adb_dnsuser="${adb_dnsuser:-"dnsmasq"}"
  114. adb_dnsdir="${adb_dnsdir:-"/tmp"}"
  115. adb_dnsheader=""
  116. adb_dnsdeny="awk '{print \"server=/\"\$0\"/\"}'"
  117. adb_dnsallow="awk '{print \"server=/\"\$0\"/#\"}'"
  118. adb_dnshalt="server=/#/"
  119. ;;
  120. unbound)
  121. adb_dnsinstance="${adb_dnsinstance:-"0"}"
  122. adb_dnsuser="${adb_dnsuser:-"unbound"}"
  123. adb_dnsdir="${adb_dnsdir:-"/var/lib/unbound"}"
  124. adb_dnsheader=""
  125. adb_dnsdeny="awk '{print \"local-zone: \042\"\$0\"\042 static\"}'"
  126. adb_dnsallow="awk '{print \"local-zone: \042\"\$0\"\042 transparent\"}'"
  127. adb_dnshalt="local-zone: \".\" static"
  128. ;;
  129. named)
  130. adb_dnsinstance="${adb_dnsinstance:-"0"}"
  131. adb_dnsuser="${adb_dnsuser:-"bind"}"
  132. adb_dnsdir="${adb_dnsdir:-"/var/lib/bind"}"
  133. adb_dnsheader="\$TTL 2h"$'\n'"@ IN SOA localhost. root.localhost. (1 6h 1h 1w 2h)"$'\n'" IN NS localhost."
  134. adb_dnsdeny="awk '{print \"\"\$0\" CNAME .\n*.\"\$0\" CNAME .\"}'"
  135. adb_dnsallow="awk '{print \"\"\$0\" CNAME rpz-passthru.\n*.\"\$0\" CNAME rpz-passthru.\"}'"
  136. adb_dnshalt="* CNAME ."
  137. ;;
  138. kresd)
  139. adb_dnsinstance="${adb_dnsinstance:-"0"}"
  140. adb_dnsuser="${adb_dnsuser:-"root"}"
  141. adb_dnsdir="${adb_dnsdir:-"/etc/kresd"}"
  142. adb_dnsheader="\$TTL 2h"$'\n'"@ IN SOA localhost. root.localhost. (1 6h 1h 1w 2h)"$'\n'" IN NS localhost."
  143. adb_dnsdeny="awk '{print \"\"\$0\" CNAME .\n*.\"\$0\" CNAME .\"}'"
  144. adb_dnsallow="awk '{print \"\"\$0\" CNAME rpz-passthru.\n*.\"\$0\" CNAME rpz-passthru.\"}'"
  145. adb_dnshalt="* CNAME ."
  146. ;;
  147. dnscrypt-proxy)
  148. adb_dnsinstance="${adb_dnsinstance:-"0"}"
  149. adb_dnsuser="${adb_dnsuser:-"nobody"}"
  150. adb_dnsdir="${adb_dnsdir:-"/tmp"}"
  151. adb_dnsheader=""
  152. adb_dnsdeny="awk '{print \$0}'"
  153. adb_dnsallow=""
  154. adb_dnshalt=""
  155. ;;
  156. esac
  157. # check adblock status
  158. #
  159. if [ ${adb_enabled} -eq 0 ]
  160. then
  161. f_extconf
  162. f_temp
  163. f_rmdns
  164. f_jsnup "disabled"
  165. f_log "info" "adblock is currently disabled, please set adb_enabled to '1' to use this service"
  166. exit 0
  167. fi
  168. if [ -d "${adb_dnsdir}" ] && [ ! -f "${adb_dnsdir}/${adb_dnsfile}" ]
  169. then
  170. printf '%s\n' "${adb_dnsheader}" > "${adb_dnsdir}/${adb_dnsfile}"
  171. fi
  172. if [ "${adb_action}" = "start" ] && [ "${adb_trigger}" = "timed" ]
  173. then
  174. sleep ${adb_triggerdelay}
  175. fi
  176. while [ ${cnt} -le 30 ]
  177. do
  178. dns_up="$(ubus -S call service list "{\"name\":\"${adb_dns}\"}" 2>/dev/null | jsonfilter -l1 -e "@[\"${adb_dns}\"].instances.*.running" 2>/dev/null)"
  179. if [ "${dns_up}" = "true" ]
  180. then
  181. break
  182. fi
  183. sleep 1
  184. cnt=$((cnt+1))
  185. done
  186. if [ "${dns_up}" != "true" ] || [ -z "${adb_dns}" ] || [ ! -x "$(command -v ${adb_dns})" ]
  187. then
  188. f_log "err" "'${adb_dns}' not running or not executable"
  189. elif [ ! -d "${adb_dnsdir}" ]
  190. then
  191. f_log "err" "'${adb_dnsdir}' backend directory not found"
  192. fi
  193. }
  194. # check environment
  195. #
  196. f_envcheck()
  197. {
  198. local ssl_lib
  199. # startup message
  200. #
  201. f_log "info" "adblock instance started ::: action: ${adb_action}, priority: ${adb_nice:-"0"}, pid: ${$}"
  202. f_jsnup "running"
  203. # check external uci config files
  204. #
  205. f_extconf
  206. # check fetch utility
  207. #
  208. case "${adb_fetchutil}" in
  209. uclient-fetch)
  210. if [ -f "/lib/libustream-ssl.so" ]
  211. then
  212. adb_fetchparm="${adb_fetchparm:-"--timeout=10 --no-check-certificate -O"}"
  213. ssl_lib="libustream-ssl"
  214. else
  215. adb_fetchparm="${adb_fetchparm:-"--timeout=10 -O"}"
  216. fi
  217. ;;
  218. wget)
  219. adb_fetchparm="${adb_fetchparm:-"--no-cache --no-cookies --max-redirect=0 --timeout=10 --no-check-certificate -O"}"
  220. ssl_lib="built-in"
  221. ;;
  222. wget-nossl)
  223. adb_fetchparm="${adb_fetchparm:-"--no-cache --no-cookies --max-redirect=0 --timeout=10 -O"}"
  224. ;;
  225. busybox)
  226. adb_fetchparm="${adb_fetchparm:-"-O"}"
  227. ;;
  228. curl)
  229. adb_fetchparm="${adb_fetchparm:-"--connect-timeout 10 --insecure -o"}"
  230. ssl_lib="built-in"
  231. ;;
  232. aria2c)
  233. adb_fetchparm="${adb_fetchparm:-"--timeout=10 --allow-overwrite=true --auto-file-renaming=false --check-certificate=false -o"}"
  234. ssl_lib="built-in"
  235. ;;
  236. esac
  237. adb_fetchutil="$(command -v "${adb_fetchutil}")"
  238. if [ ! -x "${adb_fetchutil}" ] || [ -z "${adb_fetchutil}" ] || [ -z "${adb_fetchparm}" ]
  239. then
  240. f_log "err" "download utility not found, please install 'uclient-fetch' with 'libustream-mbedtls' or the full 'wget' package"
  241. fi
  242. adb_fetchinfo="${adb_fetchutil} (${ssl_lib:-"-"})"
  243. f_temp
  244. }
  245. # create temporary files and directories
  246. #
  247. f_temp()
  248. {
  249. if [ -z "${adb_tmpdir}" ]
  250. then
  251. adb_tmpdir="$(mktemp -p /tmp -d)"
  252. adb_tmpload="$(mktemp -p ${adb_tmpdir} -tu)"
  253. adb_tmpfile="$(mktemp -p ${adb_tmpdir} -tu)"
  254. fi
  255. if [ ! -s "${adb_pidfile}" ]
  256. then
  257. printf '%s' "${$}" > "${adb_pidfile}"
  258. fi
  259. }
  260. # remove temporary files and directories
  261. #
  262. f_rmtemp()
  263. {
  264. if [ -d "${adb_tmpdir}" ]
  265. then
  266. rm -rf "${adb_tmpdir}"
  267. fi
  268. > "${adb_pidfile}"
  269. }
  270. # remove dns related files and directories
  271. #
  272. f_rmdns()
  273. {
  274. if [ -n "${adb_dns}" ]
  275. then
  276. f_hash
  277. printf '%s\n' "${adb_dnsheader}" > "${adb_dnsdir}/${adb_dnsfile}"
  278. > "${adb_dnsdir}/.${adb_dnsfile}"
  279. > "${adb_rtfile}"
  280. rm -f "${adb_backupdir}/${adb_dnsprefix}"*.gz
  281. f_hash
  282. if [ ${?} -eq 1 ]
  283. then
  284. f_dnsup
  285. fi
  286. f_rmtemp
  287. fi
  288. f_log "debug" "f_rmdns ::: dns: ${adb_dns}, dns_dir: ${adb_dnsdir}, dns_prefix: ${adb_dnsprefix}, dns_file: ${adb_dnsfile}, rt_file: ${adb_rtfile}, backup_dir: ${adb_backupdir}"
  289. }
  290. # commit uci changes
  291. #
  292. f_uci()
  293. {
  294. local change config="${1}"
  295. if [ -n "${config}" ]
  296. then
  297. change="$(uci -q changes "${config}" | awk '{ORS=" "; print $0}')"
  298. if [ -n "${change}" ]
  299. then
  300. uci_commit "${config}"
  301. case "${config}" in
  302. firewall)
  303. /etc/init.d/firewall reload >/dev/null 2>&1
  304. ;;
  305. *)
  306. /etc/init.d/"${adb_dns}" reload >/dev/null 2>&1
  307. ;;
  308. esac
  309. fi
  310. fi
  311. f_log "debug" "f_uci ::: config: ${config}, change: ${change}"
  312. }
  313. # list/overall count
  314. #
  315. f_count()
  316. {
  317. local mode="${1}"
  318. adb_cnt=0
  319. if [ -s "${adb_dnsdir}/${adb_dnsfile}" ] && ([ -z "${mode}" ] || [ "${mode}" = "final" ])
  320. then
  321. adb_cnt="$(wc -l 2>/dev/null < "${adb_dnsdir}/${adb_dnsfile}")"
  322. if [ -s "${adb_tmpdir}/tmp.add_whitelist" ]
  323. then
  324. adb_cnt="$(( ${adb_cnt} - $(wc -l 2>/dev/null < "${adb_tmpdir}/tmp.add_whitelist") ))"
  325. fi
  326. if [ "${adb_dns}" = "named" ] || [ "${adb_dns}" = "kresd" ]
  327. then
  328. adb_cnt="$(( (${adb_cnt} - $(printf '%s' "${adb_dnsheader}" | grep -c "^")) / 2 ))"
  329. fi
  330. elif [ -s "${adb_tmpfile}" ]
  331. then
  332. adb_cnt="$(wc -l 2>/dev/null < "${adb_tmpfile}")"
  333. fi
  334. }
  335. # set external config options
  336. #
  337. f_extconf()
  338. {
  339. local uci_config port port_list="53 853 5353"
  340. case "${adb_dns}" in
  341. dnsmasq)
  342. uci_config="dhcp"
  343. if [ ${adb_enabled} -eq 1 ] && [ -z "$(uci_get dhcp "@dnsmasq[${adb_dnsinstance}]" serversfile | grep -Fo "${adb_dnsdir}/${adb_dnsfile}")" ]
  344. then
  345. uci_set dhcp "@dnsmasq[${adb_dnsinstance}]" serversfile "${adb_dnsdir}/${adb_dnsfile}"
  346. elif [ ${adb_enabled} -eq 0 ] && [ -n "$(uci_get dhcp "@dnsmasq[${adb_dnsinstance}]" serversfile | grep -Fo "${adb_dnsdir}/${adb_dnsfile}")" ]
  347. then
  348. uci_remove dhcp "@dnsmasq[${adb_dnsinstance}]" serversfile
  349. fi
  350. ;;
  351. kresd)
  352. uci_config="resolver"
  353. if [ ${adb_enabled} -eq 1 ] && [ -z "$(uci_get resolver kresd rpz_file | grep -Fo "${adb_dnsdir}/${adb_dnsfile}")" ]
  354. then
  355. uci -q add_list resolver.kresd.rpz_file="${adb_dnsdir}/${adb_dnsfile}"
  356. elif [ ${adb_enabled} -eq 0 ] && [ -n "$(uci_get resolver kresd rpz_file | grep -Fo "${adb_dnsdir}/${adb_dnsfile}")" ]
  357. then
  358. uci -q del_list resolver.kresd.rpz_file="${adb_dnsdir}/${adb_dnsfile}"
  359. fi
  360. if [ ${adb_enabled} -eq 1 ] && [ ${adb_dnsflush} -eq 0 ] && [ "$(uci_get resolver kresd keep_cache)" != "1" ]
  361. then
  362. uci_set resolver kresd keep_cache "1"
  363. elif [ ${adb_enabled} -eq 0 ] || ([ ${adb_dnsflush} -eq 1 ] && [ "$(uci_get resolver kresd keep_cache)" = "1" ])
  364. then
  365. uci_set resolver kresd keep_cache "0"
  366. fi
  367. ;;
  368. esac
  369. f_uci "${uci_config}"
  370. uci_config="firewall"
  371. if [ ${adb_enabled} -eq 1 ] && [ ${adb_forcedns} -eq 1 ] && \
  372. [ -z "$(uci_get firewall adblock_dns_53)" ] && [ $(/etc/init.d/firewall enabled; printf '%u' ${?}) -eq 0 ]
  373. then
  374. for port in ${port_list}
  375. do
  376. uci_add firewall "redirect" "adblock_dns_${port}"
  377. uci_set firewall "adblock_dns_${port}" "name" "Adblock DNS, port ${port}"
  378. uci_set firewall "adblock_dns_${port}" "src" "lan"
  379. uci_set firewall "adblock_dns_${port}" "proto" "tcp udp"
  380. uci_set firewall "adblock_dns_${port}" "src_dport" "${port}"
  381. uci_set firewall "adblock_dns_${port}" "dest_port" "${port}"
  382. uci_set firewall "adblock_dns_${port}" "target" "DNAT"
  383. done
  384. elif [ -n "$(uci_get firewall adblock_dns_53)" ] && ([ ${adb_enabled} -eq 0 ] || [ ${adb_forcedns} -eq 0 ])
  385. then
  386. for port in ${port_list}
  387. do
  388. uci_remove firewall "adblock_dns_${port}"
  389. done
  390. fi
  391. f_uci "${uci_config}"
  392. }
  393. # restart of the dns backend
  394. #
  395. f_dnsup()
  396. {
  397. local dns_up cache_util cache_rc cnt=0
  398. if [ ${adb_dnsflush} -eq 0 ] && [ ${adb_enabled} -eq 1 ] && [ "${adb_rc}" -eq 0 ]
  399. then
  400. case "${adb_dns}" in
  401. dnsmasq)
  402. killall -q -HUP "${adb_dns}"
  403. cache_rc=${?}
  404. ;;
  405. unbound)
  406. cache_util="$(command -v unbound-control)"
  407. if [ -x "${cache_util}" ] && [ -d "${adb_tmpdir}" ] && [ -f "${adb_dnsdir}"/unbound.conf ]
  408. then
  409. "${cache_util}" -c "${adb_dnsdir}"/unbound.conf dump_cache > "${adb_tmpdir}"/adb_cache.dump 2>/dev/null
  410. fi
  411. "/etc/init.d/${adb_dns}" restart >/dev/null 2>&1
  412. ;;
  413. kresd)
  414. cache_util="keep_cache"
  415. "/etc/init.d/${adb_dns}" restart >/dev/null 2>&1
  416. cache_rc=${?}
  417. ;;
  418. named)
  419. cache_util="$(command -v rndc)"
  420. if [ -x "${cache_util}" ] && [ -f /etc/bind/rndc.conf ]
  421. then
  422. "${cache_util}" -c /etc/bind/rndc.conf reload >/dev/null 2>&1
  423. cache_rc=${?}
  424. else
  425. "/etc/init.d/${adb_dns}" restart >/dev/null 2>&1
  426. fi
  427. ;;
  428. *)
  429. "/etc/init.d/${adb_dns}" restart >/dev/null 2>&1
  430. ;;
  431. esac
  432. else
  433. "/etc/init.d/${adb_dns}" restart >/dev/null 2>&1
  434. fi
  435. adb_rc=1
  436. while [ ${cnt} -le 10 ]
  437. do
  438. dns_up="$(ubus -S call service list "{\"name\":\"${adb_dns}\"}" | jsonfilter -l1 -e "@[\"${adb_dns}\"].instances.*.running")"
  439. if [ "${dns_up}" = "true" ]
  440. then
  441. case "${adb_dns}" in
  442. unbound)
  443. cache_util="$(command -v unbound-control)"
  444. if [ -x "${cache_util}" ] && [ -d "${adb_tmpdir}" ] && [ -s "${adb_tmpdir}"/adb_cache.dump ]
  445. then
  446. while [ ${cnt} -le 10 ]
  447. do
  448. "${cache_util}" -c "${adb_dnsdir}"/unbound.conf load_cache < "${adb_tmpdir}"/adb_cache.dump >/dev/null 2>&1
  449. cache_rc=${?}
  450. if [ ${cache_rc} -eq 0 ]
  451. then
  452. break
  453. fi
  454. cnt=$((cnt+1))
  455. sleep 1
  456. done
  457. fi
  458. ;;
  459. esac
  460. adb_rc=0
  461. break
  462. fi
  463. cnt=$((cnt+1))
  464. sleep 1
  465. done
  466. f_log "debug" "f_dnsup ::: cache_util: ${cache_util:-"-"}, cache_rc: ${cache_rc:-"-"}, cache_flush: ${adb_dnsflush}, cache_cnt: ${cnt}, rc: ${adb_rc}"
  467. return ${adb_rc}
  468. }
  469. # backup/restore/remove blocklists
  470. #
  471. f_list()
  472. {
  473. local file mode="${1}" in_rc="${adb_rc}"
  474. case "${mode}" in
  475. backup)
  476. if [ -d "${adb_backupdir}" ]
  477. then
  478. gzip -cf "${adb_tmpfile}" 2>/dev/null > "${adb_backupdir}/${adb_dnsprefix}.${src_name}.gz"
  479. adb_rc=${?}
  480. fi
  481. ;;
  482. restore)
  483. if [ -d "${adb_backupdir}" ] && [ -f "${adb_backupdir}/${adb_dnsprefix}.${src_name}.gz" ]
  484. then
  485. gunzip -cf "${adb_backupdir}/${adb_dnsprefix}.${src_name}.gz" 2>/dev/null > "${adb_tmpfile}"
  486. adb_rc=${?}
  487. fi
  488. ;;
  489. remove)
  490. if [ -d "${adb_backupdir}" ]
  491. then
  492. rm -f "${adb_backupdir}/${adb_dnsprefix}.${src_name}.gz"
  493. fi
  494. adb_rc=${?}
  495. ;;
  496. merge)
  497. for file in "${adb_tmpfile}".*
  498. do
  499. cat "${file}" 2>/dev/null >> "${adb_tmpdir}/${adb_dnsfile}"
  500. if [ ${?} -ne 0 ]
  501. then
  502. adb_rc=${?}
  503. break
  504. fi
  505. rm -f "${file}"
  506. done
  507. adb_tmpfile="${adb_tmpdir}/${adb_dnsfile}"
  508. ;;
  509. final)
  510. > "${adb_dnsdir}/${adb_dnsfile}"
  511. if [ -s "${adb_tmpdir}/tmp.add_whitelist" ]
  512. then
  513. cat "${adb_tmpdir}/tmp.add_whitelist" >> "${adb_dnsdir}/${adb_dnsfile}"
  514. fi
  515. if [ -s "${adb_tmpdir}/tmp.rem_whitelist" ]
  516. then
  517. grep -vf "${adb_tmpdir}/tmp.rem_whitelist" "${adb_tmpdir}/${adb_dnsfile}" | eval "${adb_dnsdeny}" >> "${adb_dnsdir}/${adb_dnsfile}"
  518. else
  519. eval "${adb_dnsdeny}" "${adb_tmpdir}/${adb_dnsfile}" >> "${adb_dnsdir}/${adb_dnsfile}"
  520. fi
  521. if [ ${?} -eq 0 ] && [ -n "${adb_dnsheader}" ]
  522. then
  523. printf '%s\n' "${adb_dnsheader}" | cat - "${adb_dnsdir}/${adb_dnsfile}" > "${adb_tmpdir}/${adb_dnsfile}"
  524. mv -f "${adb_tmpdir}/${adb_dnsfile}" "${adb_dnsdir}/${adb_dnsfile}"
  525. fi
  526. adb_rc=${?}
  527. ;;
  528. esac
  529. f_count "${mode}"
  530. f_log "debug" "f_list ::: name: ${src_name:-"-"}, mode: ${mode}, cnt: ${adb_cnt}, in_rc: ${in_rc}, out_rc: ${adb_rc}"
  531. }
  532. # top level domain compression
  533. #
  534. f_tld()
  535. {
  536. local cnt cnt_srt cnt_tld source="${1}" temp="${1}.tld"
  537. cnt="$(wc -l 2>/dev/null < "${source}")"
  538. awk 'BEGIN{FS="."}{for(f=NF;f>1;f--)printf "%s.",$f;print $1}' "${source}" > "${temp}"
  539. if [ ${?} -eq 0 ]
  540. then
  541. sort -u "${temp}" > "${source}"
  542. if [ ${?} -eq 0 ]
  543. then
  544. cnt_srt="$(wc -l 2>/dev/null < "${source}")"
  545. awk '{if(NR==1){tld=$NF};while(getline){if($NF!~tld"\\."){print tld;tld=$NF}}print tld}' "${source}" > "${temp}"
  546. if [ ${?} -eq 0 ]
  547. then
  548. awk 'BEGIN{FS="."}{for(f=NF;f>1;f--)printf "%s.",$f;print $1}' "${temp}" > "${source}"
  549. if [ ${?} -eq 0 ]
  550. then
  551. cnt_tld="$(wc -l 2>/dev/null < "${source}")"
  552. rm -f "${temp}"
  553. else
  554. mv -f "${temp}" > "${source}"
  555. fi
  556. fi
  557. else
  558. mv -f "${temp}" "${source}"
  559. fi
  560. fi
  561. f_log "debug" "f_tld ::: source: ${source}, cnt: ${cnt:-"-"}, cnt_srt: ${cnt_srt:-"-"}, cnt_tld: ${cnt_tld:-"-"}"
  562. }
  563. # blocklist hash compare
  564. #
  565. f_hash()
  566. {
  567. local hash hash_rc=1
  568. if [ -x "${adb_hashutil}" ] && [ -f "${adb_dnsdir}/${adb_dnsfile}" ]
  569. then
  570. hash="$(${adb_hashutil} "${adb_dnsdir}/${adb_dnsfile}" 2>/dev/null | awk '{print $1}')"
  571. if [ -z "${adb_hashold}" ] && [ -n "${hash}" ]
  572. then
  573. adb_hashold="${hash}"
  574. elif [ -z "${adb_hashnew}" ] && [ -n "${hash}" ]
  575. then
  576. adb_hashnew="${hash}"
  577. fi
  578. if [ -n "${adb_hashold}" ] && [ -n "${adb_hashnew}" ]
  579. then
  580. if [ "${adb_hashold}" = "${adb_hashnew}" ]
  581. then
  582. hash_rc=0
  583. fi
  584. adb_hashold=""
  585. adb_hashnew=""
  586. fi
  587. fi
  588. f_log "debug" "f_hash ::: hash_util: ${adb_hashutil}, hash: ${hash}, out_rc: ${hash_rc}"
  589. return ${hash_rc}
  590. }
  591. # suspend/resume adblock processing
  592. #
  593. f_switch()
  594. {
  595. local status cnt mode="${1}"
  596. json_load_file "${adb_rtfile}" >/dev/null 2>&1
  597. json_select "data"
  598. json_get_var status "adblock_status"
  599. json_get_var cnt "overall_domains"
  600. if [ "${mode}" = "suspend" ] && [ "${status}" = "enabled" ]
  601. then
  602. if [ ${cnt%% *} -gt 0 ] && [ -s "${adb_dnsdir}/${adb_dnsfile}" ]
  603. then
  604. f_hash
  605. cat "${adb_dnsdir}/${adb_dnsfile}" > "${adb_dnsdir}/.${adb_dnsfile}"
  606. printf '%s\n' "${adb_dnsheader}" > "${adb_dnsdir}/${adb_dnsfile}"
  607. f_hash
  608. fi
  609. elif [ "${mode}" = "resume" ] && [ "${status}" = "paused" ]
  610. then
  611. if [ ${cnt%% *} -gt 0 ] && [ -s "${adb_dnsdir}/.${adb_dnsfile}" ]
  612. then
  613. f_hash
  614. cat "${adb_dnsdir}/.${adb_dnsfile}" > "${adb_dnsdir}/${adb_dnsfile}"
  615. > "${adb_dnsdir}/.${adb_dnsfile}"
  616. f_hash
  617. fi
  618. fi
  619. if [ ${?} -eq 1 ]
  620. then
  621. f_temp
  622. f_dnsup
  623. f_jsnup "${mode}"
  624. f_log "info" "${mode} adblock processing"
  625. f_rmtemp
  626. exit 0
  627. fi
  628. }
  629. # query blocklist for certain (sub-)domains
  630. #
  631. f_query()
  632. {
  633. local search result prefix suffix field domain="${1}" tld="${1#*.}"
  634. if [ -z "${domain}" ] || [ "${domain}" = "${tld}" ]
  635. then
  636. printf '%s\n' "::: invalid domain input, please submit a single domain, e.g. 'doubleclick.net'"
  637. else
  638. case "${adb_dns}" in
  639. dnsmasq)
  640. prefix=".*[\/\.]"
  641. suffix="(\/)"
  642. field=2
  643. ;;
  644. unbound)
  645. prefix=".*[\"\.]"
  646. suffix="(static)"
  647. field=3
  648. ;;
  649. named)
  650. prefix="[^\*].*[\.]"
  651. suffix="( \.)"
  652. field=1
  653. ;;
  654. kresd)
  655. prefix="[^\*].*[\.]"
  656. suffix="( \.)"
  657. field=1
  658. ;;
  659. dnscrypt-proxy)
  660. prefix=".*[\.]"
  661. suffix=""
  662. field=1
  663. ;;
  664. esac
  665. while [ "${domain}" != "${tld}" ]
  666. do
  667. search="${domain//./\.}"
  668. result="$(awk -F '/|\"| ' "/^($search|${prefix}+${search}.*${suffix}$)/{i++;{printf(\" + %s\n\",\$${field})};if(i>9){printf(\" + %s\n\",\"[...]\");exit}}" "${adb_dnsdir}/${adb_dnsfile}")"
  669. printf '%s\n' "::: results for domain '${domain}'"
  670. printf '%s\n' "${result:-" - no match"}"
  671. domain="${tld}"
  672. tld="${domain#*.}"
  673. done
  674. fi
  675. }
  676. # update runtime information
  677. #
  678. f_jsnup()
  679. {
  680. local run_time bg_pid status="${1:-"enabled"}" mode="normal mode" no_mail=0
  681. if [ ${adb_rc} -gt 0 ]
  682. then
  683. status="error"
  684. run_time="$(/bin/date "+%d.%m.%Y %H:%M:%S")"
  685. fi
  686. if [ "${status}" = "enabled" ]
  687. then
  688. run_time="$(/bin/date "+%d.%m.%Y %H:%M:%S")"
  689. fi
  690. if [ "${status}" = "suspend" ]
  691. then
  692. status="paused"
  693. fi
  694. if [ "${status}" = "resume" ]
  695. then
  696. no_mail=1
  697. status="enabled"
  698. fi
  699. if [ ${adb_backup_mode} -eq 1 ]
  700. then
  701. mode="backup mode"
  702. fi
  703. json_load_file "${adb_rtfile}" >/dev/null 2>&1
  704. json_select "data" >/dev/null 2>&1
  705. if [ ${?} -eq 0 ]
  706. then
  707. if [ -z "${adb_fetchinfo}" ]
  708. then
  709. json_get_var adb_fetchinfo "fetch_utility"
  710. fi
  711. if [ -z "${adb_cnt}" ]
  712. then
  713. json_get_var adb_cnt "overall_domains"
  714. adb_cnt="${adb_cnt%% *}"
  715. fi
  716. if [ -z "${run_time}" ]
  717. then
  718. json_get_var run_time "last_rundate"
  719. fi
  720. fi
  721. > "${adb_rtfile}"
  722. json_load_file "${adb_rtfile}" >/dev/null 2>&1
  723. json_init
  724. json_add_object "data"
  725. json_add_string "adblock_status" "${status}"
  726. json_add_string "adblock_version" "${adb_ver}"
  727. json_add_string "overall_domains" "${adb_cnt:-0} (${mode})"
  728. json_add_string "fetch_utility" "${adb_fetchinfo:-"-"}"
  729. json_add_string "dns_backend" "${adb_dns} (${adb_dnsdir})"
  730. json_add_string "last_rundate" "${run_time:-"-"}"
  731. json_add_string "system_release" "${adb_sysver}"
  732. json_close_object
  733. json_dump > "${adb_rtfile}"
  734. if [ ${adb_notify} -eq 1 ] && [ ${no_mail} -eq 0 ] && [ -x /etc/adblock/adblock.notify ] && \
  735. ([ "${status}" = "error" ] || ([ "${status}" = "enabled" ] && [ ${adb_cnt} -le ${adb_notifycnt} ]))
  736. then
  737. (/etc/adblock/adblock.notify >/dev/null 2>&1)&
  738. bg_pid=${!}
  739. fi
  740. f_log "debug" "f_jsnup ::: status: ${status}, mode: ${mode}, cnt: ${adb_cnt}, notify: ${adb_notify}, notify_cnt: ${adb_notifycnt}, notify_pid: ${bg_pid:-"-"}"
  741. }
  742. # write to syslog
  743. #
  744. f_log()
  745. {
  746. local class="${1}" log_msg="${2}"
  747. if [ -n "${log_msg}" ] && ([ "${class}" != "debug" ] || [ ${adb_debug} -eq 1 ])
  748. then
  749. logger -p "${class}" -t "adblock-${adb_ver}[${$}]" "${log_msg}"
  750. if [ "${class}" = "err" ]
  751. then
  752. f_rmdns
  753. f_jsnup
  754. logger -p "${class}" -t "adblock-${adb_ver}[${$}]" "Please also check 'https://github.com/openwrt/packages/blob/master/net/adblock/files/README.md'"
  755. exit 1
  756. fi
  757. fi
  758. }
  759. # main function for blocklist processing
  760. #
  761. f_main()
  762. {
  763. local tmp_load tmp_file src_name src_rset src_url src_log src_arc src_cat cat list entry suffix mem_total mem_free enabled cnt=1
  764. mem_total="$(awk '/^MemTotal/ {print int($2/1000)}' "/proc/meminfo" 2>/dev/null)"
  765. mem_free="$(awk '/^MemFree/ {print int($2/1000)}' "/proc/meminfo" 2>/dev/null)"
  766. tmp_load="${adb_tmpload}"
  767. tmp_file="${adb_tmpfile}"
  768. > "${adb_dnsdir}/.${adb_dnsfile}"
  769. > "${adb_tmpdir}/tmp.raw_whitelist"
  770. > "${adb_tmpdir}/tmp.add_whitelist"
  771. > "${adb_tmpdir}/tmp.rem_whitelist"
  772. f_log "debug" "f_main ::: dns: ${adb_dns}, fetch_util: ${adb_fetchinfo}, backup: ${adb_backup}, backup_mode: ${adb_backup_mode}, dns_jail: ${adb_jail}, force_srt: ${adb_forcesrt}, force_dns: ${adb_forcedns}, mem_total: ${mem_total:-0}, mem_free: ${mem_free:-0}, max_queue: ${adb_maxqueue}"
  773. # prepare whitelist entries
  774. #
  775. if [ -s "${adb_whitelist}" ]
  776. then
  777. adb_whitelist_rset="/^([[:alnum:]_-]+\.)+[[:alpha:]]+([[:space:]]|$)/{print tolower(\$1)}"
  778. awk "${adb_whitelist_rset}" "${adb_whitelist}" > "${adb_tmpdir}/tmp.raw_whitelist"
  779. f_tld "${adb_tmpdir}/tmp.raw_whitelist"
  780. adb_whitelist_rset="/^([[:alnum:]_-]+\.)+[[:alpha:]]+([[:space:]]|$)/{gsub(\"\\\.\",\"\\\.\",\$1);print tolower(\"^\"\$1\"\\\|\\\.\"\$1)}"
  781. awk "${adb_whitelist_rset}" "${adb_tmpdir}/tmp.raw_whitelist" > "${adb_tmpdir}/tmp.rem_whitelist"
  782. if [ -n "${adb_dnsallow}" ]
  783. then
  784. eval "${adb_dnsallow}" "${adb_tmpdir}/tmp.raw_whitelist" > "${adb_tmpdir}/tmp.add_whitelist"
  785. fi
  786. fi
  787. # build 'dnsjail' list
  788. #
  789. if [ ${adb_jail} -eq 1 ]
  790. then
  791. cat "${adb_tmpdir}/tmp.add_whitelist" > "/tmp/${adb_dnsjail}"
  792. printf '%s\n' "${adb_dnshalt}" >> "/tmp/${adb_dnsjail}"
  793. if [ -n "${adb_dnsheader}" ]
  794. then
  795. printf '%s\n' "${adb_dnsheader}" | cat - "/tmp/${adb_dnsjail}" > "${adb_tmpdir}/tmp.dnsjail"
  796. cat "${adb_tmpdir}/tmp.dnsjail" > "/tmp/${adb_dnsjail}"
  797. fi
  798. fi
  799. # main loop
  800. #
  801. for src_name in ${adb_sources}
  802. do
  803. enabled="$(eval printf '%s' \"\${enabled_${src_name}\}\")"
  804. src_url="$(eval printf '%s' \"\${adb_src_${src_name}\}\")"
  805. src_rset="$(eval printf '%s' \"\${adb_src_rset_${src_name}\}\")"
  806. src_cat="$(eval printf '%s' \"\${adb_src_cat_${src_name}\}\")"
  807. adb_tmpload="${tmp_load}.${src_name}"
  808. adb_tmpfile="${tmp_file}.${src_name}"
  809. # basic pre-checks
  810. #
  811. f_log "debug" "f_main ::: name: ${src_name}, enabled: ${enabled}"
  812. if [ "${enabled}" != "1" ] || [ -z "${src_url}" ] || [ -z "${src_rset}" ]
  813. then
  814. f_list remove
  815. continue
  816. fi
  817. # backup mode
  818. #
  819. if [ ${adb_backup_mode} -eq 1 ] && [ "${adb_action}" = "start" ] && [ "${src_name}" != "blacklist" ]
  820. then
  821. f_list restore
  822. if [ ${adb_rc} -eq 0 ] && [ -s "${adb_tmpfile}" ]
  823. then
  824. if ([ ${mem_total} -lt 64 ] || [ ${mem_free} -lt 40 ]) && [ ${adb_forcesrt} -eq 0 ]
  825. then
  826. f_tld "${adb_tmpfile}"
  827. fi
  828. continue
  829. fi
  830. fi
  831. # download queue processing
  832. #
  833. if [ "${src_name}" = "blacklist" ]
  834. then
  835. if [ -s "${src_url}" ]
  836. then
  837. (
  838. src_log="$(cat "${src_url}" > "${adb_tmpload}" 2>&1)"
  839. adb_rc=${?}
  840. if [ ${adb_rc} -eq 0 ] && [ -s "${adb_tmpload}" ]
  841. then
  842. awk "${src_rset}" "${adb_tmpload}" 2>/dev/null > "${adb_tmpfile}"
  843. adb_rc=${?}
  844. if [ ${adb_rc} -eq 0 ] && [ -s "${adb_tmpfile}" ]
  845. then
  846. rm -f "${adb_tmpload}"
  847. f_list download
  848. if ([ ${mem_total} -lt 64 ] || [ ${mem_free} -lt 40 ]) && [ ${adb_forcesrt} -eq 0 ]
  849. then
  850. f_tld "${adb_tmpfile}"
  851. fi
  852. fi
  853. else
  854. src_log="$(printf '%s' "${src_log}" | awk '{ORS=" ";print $0}')"
  855. f_log "debug" "f_main ::: name: ${src_name}, url: ${src_url}, rc: ${adb_rc}, log: ${src_log:-"-"}"
  856. fi
  857. ) &
  858. else
  859. continue
  860. fi
  861. elif [ -n "${src_cat}" ]
  862. then
  863. (
  864. src_arc="${adb_tmpdir}/${src_url##*/}"
  865. src_log="$("${adb_fetchutil}" ${adb_fetchparm} "${src_arc}" "${src_url}" 2>&1)"
  866. adb_rc=${?}
  867. if [ ${adb_rc} -eq 0 ] && [ -s "${src_arc}" ]
  868. then
  869. list="$(tar -tzf "${src_arc}")"
  870. suffix="$(eval printf '%s' \"\${adb_src_suffix_${src_name}:-\"domains\"\}\")"
  871. for cat in ${src_cat}
  872. do
  873. entry="$(printf '%s' "${list}" | grep -E "[\^/]+${cat}/${suffix}")"
  874. if [ -n "${entry}" ]
  875. then
  876. tar -xOzf "${src_arc}" "${entry}" >> "${adb_tmpload}"
  877. adb_rc=${?}
  878. if [ ${adb_rc} -ne 0 ]
  879. then
  880. break
  881. fi
  882. fi
  883. done
  884. else
  885. src_log="$(printf '%s' "${src_log}" | awk '{ORS=" ";print $0}')"
  886. f_log "debug" "f_main ::: name: ${src_name}, url: ${src_url}, rc: ${adb_rc}, log: ${src_log:-"-"}"
  887. fi
  888. if [ ${adb_rc} -eq 0 ] && [ -s "${adb_tmpload}" ]
  889. then
  890. rm -f "${src_arc}"
  891. awk "${src_rset}" "${adb_tmpload}" 2>/dev/null > "${adb_tmpfile}"
  892. adb_rc=${?}
  893. if [ ${adb_rc} -eq 0 ] && [ -s "${adb_tmpfile}" ]
  894. then
  895. rm -f "${adb_tmpload}"
  896. f_list download
  897. if [ ${adb_backup} -eq 1 ]
  898. then
  899. f_list backup
  900. fi
  901. if ([ ${mem_total} -lt 64 ] || [ ${mem_free} -lt 40 ]) && [ ${adb_forcesrt} -eq 0 ]
  902. then
  903. f_tld "${adb_tmpfile}"
  904. fi
  905. elif [ ${adb_backup} -eq 1 ]
  906. then
  907. f_list restore
  908. fi
  909. elif [ ${adb_backup} -eq 1 ]
  910. then
  911. f_list restore
  912. fi
  913. ) &
  914. else
  915. (
  916. src_log="$("${adb_fetchutil}" ${adb_fetchparm} "${adb_tmpload}" "${src_url}" 2>&1)"
  917. adb_rc=${?}
  918. if [ ${adb_rc} -eq 0 ] && [ -s "${adb_tmpload}" ]
  919. then
  920. awk "${src_rset}" "${adb_tmpload}" 2>/dev/null > "${adb_tmpfile}"
  921. adb_rc=${?}
  922. if [ ${adb_rc} -eq 0 ] && [ -s "${adb_tmpfile}" ]
  923. then
  924. rm -f "${adb_tmpload}"
  925. f_list download
  926. if [ ${adb_backup} -eq 1 ]
  927. then
  928. f_list backup
  929. fi
  930. if ([ ${mem_total} -lt 64 ] || [ ${mem_free} -lt 40 ]) && [ ${adb_forcesrt} -eq 0 ]
  931. then
  932. f_tld "${adb_tmpfile}"
  933. fi
  934. elif [ ${adb_backup} -eq 1 ]
  935. then
  936. f_list restore
  937. fi
  938. else
  939. src_log="$(printf '%s' "${src_log}" | awk '{ORS=" ";print $0}')"
  940. f_log "debug" "f_main ::: name: ${src_name}, url: ${src_url}, rc: ${adb_rc}, log: ${src_log:-"-"}"
  941. if [ ${adb_backup} -eq 1 ]
  942. then
  943. f_list restore
  944. fi
  945. fi
  946. ) &
  947. fi
  948. hold=$(( cnt % adb_maxqueue ))
  949. if [ ${hold} -eq 0 ]
  950. then
  951. wait
  952. fi
  953. cnt=$(( cnt + 1 ))
  954. done
  955. # list merge
  956. #
  957. wait
  958. src_name="overall"
  959. adb_tmpfile="${tmp_file}"
  960. f_list merge
  961. # overall sort and conditional dns restart
  962. #
  963. f_hash
  964. if [ -s "${adb_tmpdir}/${adb_dnsfile}" ]
  965. then
  966. if ([ ${mem_total} -ge 64 ] && [ ${mem_free} -ge 40 ]) || [ ${adb_forcesrt} -eq 1 ]
  967. then
  968. f_tld "${adb_tmpdir}/${adb_dnsfile}"
  969. fi
  970. f_list final
  971. else
  972. > "${adb_dnsdir}/${adb_dnsfile}"
  973. fi
  974. chown "${adb_dnsuser}" "${adb_dnsdir}/${adb_dnsfile}" 2>/dev/null
  975. f_hash
  976. if [ ${?} -eq 1 ]
  977. then
  978. f_dnsup
  979. fi
  980. f_jsnup
  981. if [ ${?} -eq 0 ]
  982. then
  983. f_log "info" "blocklist with overall ${adb_cnt} domains loaded successfully (${adb_sysver})"
  984. else
  985. f_log "err" "dns backend restart with active blocklist failed"
  986. fi
  987. f_rmtemp
  988. exit ${adb_rc}
  989. }
  990. # trace dns queries via tcpdump and prepare a report
  991. #
  992. f_report()
  993. {
  994. local bg_pid total blocked percent rep_clients rep_domains rep_blocked index hold ports cnt=0 print="${1:-"true"}"
  995. if [ ! -x "${adb_reputil}" ]
  996. then
  997. f_log "info" "Please install the package 'tcpdump-mini' manually to use the adblock reporting feature!"
  998. return 0
  999. fi
  1000. bg_pid="$(pgrep -f "^${adb_reputil}.*adb_report\.pcap$" | awk '{ORS=" "; print $1}')"
  1001. if [ ${adb_report} -eq 0 ] || ([ -n "${bg_pid}" ] && ([ "${adb_action}" = "stop" ] || [ "${adb_action}" = "restart" ]))
  1002. then
  1003. if [ -n "${bg_pid}" ]
  1004. then
  1005. kill -HUP ${bg_pid}
  1006. while $(kill -0 ${bg_pid} 2>/dev/null)
  1007. do
  1008. sleep 1
  1009. done
  1010. unset bg_pid
  1011. fi
  1012. fi
  1013. if [ -z "${bg_pid}" ] && [ "${adb_action}" != "report" ] && [ "${adb_action}" != "stop" ]
  1014. then
  1015. for port in ${adb_replisten}
  1016. do
  1017. if [ -z "${ports}" ]
  1018. then
  1019. ports="port ${port}"
  1020. else
  1021. ports="${ports} or port ${port}"
  1022. fi
  1023. done
  1024. ("${adb_reputil}" -nn -s0 -l -i ${adb_repiface} ${ports} -C${adb_repchunksize} -W${adb_repchunkcnt} -w "${adb_repdir}/adb_report.pcap" >/dev/null 2>&1 &)
  1025. fi
  1026. if [ "${adb_action}" = "report" ]
  1027. then
  1028. > "${adb_repdir}/adb_report.raw"
  1029. for file in "${adb_repdir}"/adb_report.pcap*
  1030. do
  1031. (
  1032. "${adb_reputil}" -nn -tttt -r $file 2>/dev/null | \
  1033. awk -v cnt=${cnt} '!/\.lan\. /&&/ A[\? ]+|NXDomain/{a=$1;b=substr($2,0,8);c=$4;sub(/\.[0-9]+$/,"",c); \
  1034. d=cnt $7;e=$(NF-1);sub(/[0-9]\/[0-9]\/[0-9]/,"NX",e);sub(/\.$/,"",e);sub(/([0-9]{1,3}\.){3}[0-9]{1,3}/,"OK",e);printf("%s\t%s\t%s\t%s\t%s\n", a,b,c,d,e)}' >> "${adb_repdir}/adb_report.raw"
  1035. )&
  1036. hold=$(( cnt % adb_maxqueue ))
  1037. if [ ${hold} -eq 0 ]
  1038. then
  1039. wait
  1040. fi
  1041. cnt=$(( cnt + 1 ))
  1042. done
  1043. wait
  1044. if [ -s "${adb_repdir}/adb_report.raw" ]
  1045. then
  1046. awk '{printf("%s\t%s\t%s\t%s\t%s\t%s\n", $4,$5,$1,$2,$3,$4)}' "${adb_repdir}/adb_report.raw" | \
  1047. sort -ur | uniq -uf2 | awk '{currA=($6+0);currB=$6;currC=substr($6,length($6),1); \
  1048. if(reqA==currB){reqA=0;printf("%s\t%s\n",d,$2)}else if(currC=="+"){reqA=currA;d=$3"\t"$4"\t"$5"\t"$2}}' | sort -ur > "${adb_repdir}/adb_report"
  1049. fi
  1050. if [ -s "${adb_repdir}/adb_report" ]
  1051. then
  1052. total="$(wc -l < ${adb_repdir}/adb_report)"
  1053. blocked="$(awk '{if($5=="NX")print $4}' ${adb_repdir}/adb_report | wc -l)"
  1054. percent="$(awk -v t=${total} -v b=${blocked} 'BEGIN{printf("%.2f %s\n",b/t*100, "%")}')"
  1055. rep_clients="$(awk '{print $3}' ${adb_repdir}/adb_report | sort | uniq -c | sort -r | awk '{ORS=" ";if(NR<=10) printf("%s_%s ",$1,$2)}')"
  1056. rep_domains="$(awk '{if($5!="NX")print $4}' ${adb_repdir}/adb_report | sort | uniq -c | sort -r | awk '{ORS=" ";if(NR<=10)printf("%s_%s ",$1,$2)}')"
  1057. rep_blocked="$(awk '{if($5=="NX")print $4}' ${adb_repdir}/adb_report | sort | uniq -c | sort -r | awk '{ORS=" ";if(NR<=10)printf("%s_%s ",$1,$2)}')"
  1058. > "${adb_repdir}/adb_report.json"
  1059. json_load_file "${adb_repdir}/adb_report.json" >/dev/null 2>&1
  1060. json_init
  1061. json_add_object "data"
  1062. json_add_string "start_date" "$(awk 'END{printf("%s",$1)}' ${adb_repdir}/adb_report)"
  1063. json_add_string "start_time" "$(awk 'END{printf("%s",$2)}' ${adb_repdir}/adb_report)"
  1064. json_add_string "end_date" "$(awk 'NR==1{printf("%s",$1)}' ${adb_repdir}/adb_report)"
  1065. json_add_string "end_time" "$(awk 'NR==1{printf("%s",$2)}' ${adb_repdir}/adb_report)"
  1066. json_add_string "total" "${total}"
  1067. json_add_string "blocked" "${blocked}"
  1068. json_add_string "percent" "${percent}"
  1069. json_close_array
  1070. json_add_array "top_clients"
  1071. for client in ${rep_clients}
  1072. do
  1073. json_add_object
  1074. json_add_string "count" "${client%_*}"
  1075. json_add_string "address" "${client#*_}"
  1076. json_close_object
  1077. done
  1078. json_close_array
  1079. json_add_array "top_domains"
  1080. for domain in ${rep_domains}
  1081. do
  1082. json_add_object
  1083. json_add_string "count" "${domain%_*}"
  1084. json_add_string "address" "${domain#*_}"
  1085. json_close_object
  1086. done
  1087. json_close_array
  1088. json_add_array "top_blocked"
  1089. for block in ${rep_blocked}
  1090. do
  1091. json_add_object
  1092. json_add_string "count" "${block%_*}"
  1093. json_add_string "address" "${block#*_}"
  1094. json_close_object
  1095. done
  1096. json_close_object
  1097. json_dump > "${adb_repdir}/adb_report.json"
  1098. fi
  1099. rm -f "${adb_repdir}/adb_report.raw"
  1100. if [ "${print}" = "true" ]
  1101. then
  1102. if [ -s "${adb_repdir}/adb_report.json" ]
  1103. then
  1104. printf "%s\n%s\n%s\n" ":::" "::: Adblock DNS-Query Report" ":::"
  1105. json_load_file "${adb_repdir}/adb_report.json"
  1106. json_select "data"
  1107. json_get_keys keylist
  1108. for key in ${keylist}
  1109. do
  1110. json_get_var value "${key}"
  1111. eval "${key}=\"${value}\""
  1112. done
  1113. printf " + %s\n + %s\n" "Start ::: ${start_date}, ${start_time}" "End ::: ${end_date}, ${end_time}"
  1114. printf " + %s\n + %s %s\n" "Total ::: ${total}" "Blocked ::: ${blocked}" "(${percent})"
  1115. json_select ".."
  1116. if json_get_type Status "top_clients" && [ "${Status}" = "array" ]
  1117. then
  1118. printf "%s\n%s\n" ":::" "::: Top 10 Clients"
  1119. json_select "top_clients"
  1120. index=1
  1121. while json_get_type Status ${index} && [ "${Status}" = "object" ]
  1122. do
  1123. json_get_values client ${index}
  1124. printf " + %-9s::: %s\n" ${client}
  1125. index=$((index + 1))
  1126. done
  1127. fi
  1128. json_select ".."
  1129. if json_get_type Status "top_domains" && [ "${Status}" = "array" ]
  1130. then
  1131. printf "%s\n%s\n" ":::" "::: Top 10 Domains"
  1132. json_select "top_domains"
  1133. index=1
  1134. while json_get_type Status ${index} && [ "${Status}" = "object" ]
  1135. do
  1136. json_get_values domain ${index}
  1137. printf " + %-9s::: %s\n" ${domain}
  1138. index=$((index + 1))
  1139. done
  1140. fi
  1141. json_select ".."
  1142. if json_get_type Status "top_blocked" && [ "${Status}" = "array" ]
  1143. then
  1144. printf "%s\n%s\n" ":::" "::: Top 10 Blocked Domains"
  1145. json_select "top_blocked"
  1146. index=1
  1147. while json_get_type Status ${index} && [ "${Status}" = "object" ]
  1148. do
  1149. json_get_values blocked ${index}
  1150. printf " + %-9s::: %s\n" ${blocked}
  1151. index=$((index + 1))
  1152. done
  1153. fi
  1154. else
  1155. printf "%s\n" "::: no reporting data available yet"
  1156. fi
  1157. fi
  1158. fi
  1159. f_log "debug" "f_report ::: action: ${adb_action}, report: ${adb_report}, print: ${print}, reputil: ${adb_reputil}, repdir: ${adb_repdir}, repiface: ${adb_repiface}, replisten: ${adb_replisten}, repchunksize: ${adb_repchunksize}, repchunkcnt: ${adb_repchunkcnt}, bg_pid: ${bg_pid}"
  1160. }
  1161. # source required system libraries
  1162. #
  1163. if [ -r "/lib/functions.sh" ] && [ -r "/usr/share/libubox/jshn.sh" ]
  1164. then
  1165. . "/lib/functions.sh"
  1166. . "/usr/share/libubox/jshn.sh"
  1167. else
  1168. f_log "err" "system libraries not found"
  1169. fi
  1170. # handle different adblock actions
  1171. #
  1172. f_envload
  1173. case "${adb_action}" in
  1174. stop)
  1175. f_report false
  1176. f_rmdns
  1177. ;;
  1178. restart)
  1179. f_report false
  1180. f_rmdns
  1181. f_envcheck
  1182. f_main
  1183. ;;
  1184. suspend)
  1185. f_switch suspend
  1186. ;;
  1187. resume)
  1188. f_switch resume
  1189. ;;
  1190. report)
  1191. f_report "${2}"
  1192. ;;
  1193. query)
  1194. f_query "${2}"
  1195. ;;
  1196. start|reload)
  1197. f_report false
  1198. f_envcheck
  1199. f_main
  1200. ;;
  1201. esac