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.

434 lines
13 KiB

  1. ##############################################
  2. # function library used by adblock-update.sh #
  3. # written by Dirk Brenken (dirk@brenken.org) #
  4. ##############################################
  5. #############################################
  6. # f_envcheck: check environment prerequisites
  7. #
  8. f_envcheck()
  9. {
  10. # source in json helpers library
  11. #
  12. if [ -r "/usr/share/libubox/jshn.sh" ]
  13. then
  14. . "/usr/share/libubox/jshn.sh"
  15. else
  16. /usr/bin/logger -t "adblock[${pid}]" "json helpers library not found"
  17. f_deltemp
  18. exit 10
  19. fi
  20. # check adblock network device configuration
  21. #
  22. if [ ! -d "/sys/class/net/${adb_dev}" ]
  23. then
  24. /usr/bin/logger -t "adblock[${pid}]" "invalid adblock network device input (${adb_dev})"
  25. f_deltemp
  26. exit 15
  27. fi
  28. # check adblock network interface configuration
  29. #
  30. check_if="$(printf "${adb_if}" | sed -n '/[^_0-9A-Za-z]/p')"
  31. banned_if="$(printf "${adb_if}" | sed -n '/.*lan.*\|.*wan.*\|.*switch.*\|main\|globals\|loopback\|px5g/p')"
  32. if [ -n "${check_if}" ] || [ -n "${banned_if}" ]
  33. then
  34. /usr/bin/logger -t "adblock[${pid}]" "invalid adblock network interface input (${adb_if})"
  35. f_deltemp
  36. exit 20
  37. fi
  38. # check adblock ip address configuration
  39. #
  40. check_ip="$(printf "${adb_ip}" | sed -n '/\([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}/p')"
  41. if [ -z "${check_ip}" ]
  42. then
  43. /usr/bin/logger -t "adblock[${pid}]" "invalid adblock ip address input (${adb_ip})"
  44. f_deltemp
  45. exit 25
  46. fi
  47. # check adblock blacklist/whitelist configuration
  48. #
  49. if [ ! -r "${adb_blacklist}" ] || [ ! -r "${adb_whitelist}" ]
  50. then
  51. /usr/bin/logger -t "adblock[${pid}]" "adblock blacklist or whitelist not found"
  52. f_deltemp
  53. exit 30
  54. fi
  55. # check wan update configuration
  56. #
  57. if [ -n "${wan_dev}" ]
  58. then
  59. wan_ok="true"
  60. else
  61. wan_ok="false"
  62. /usr/bin/logger -t "adblock[${pid}]" "wan update check will be disabled"
  63. fi
  64. # check ntp sync configuration
  65. #
  66. if [ -n "${ntp_srv}" ]
  67. then
  68. ntp_ok="true"
  69. else
  70. ntp_ok="false"
  71. /usr/bin/logger -t "adblock[${pid}]" "ntp time sync will be disabled"
  72. fi
  73. # check backup configuration
  74. #
  75. if [ -n "${backup_dir}" ] && [ -d "${backup_dir}" ]
  76. then
  77. backup_ok="true"
  78. mounts="${backup_dir} ${tmp_dir}"
  79. else
  80. backup_ok="false"
  81. mounts="${tmp_dir}"
  82. /usr/bin/logger -t "adblock[${pid}]" "backup/restore will be disabled"
  83. fi
  84. # check error log configuration
  85. #
  86. if [ "${log_file}" = "/dev/stdout" ]
  87. then
  88. log_ok="true"
  89. log_file="/proc/self/fd/1"
  90. elif [ -n "${log_file}" ] && [ "${backup_ok}" = "true" ] && [ "${ntp_ok}" = "true" ]
  91. then
  92. log_ok="true"
  93. else
  94. log_ok="false"
  95. log_file="/dev/null"
  96. /usr/bin/logger -t "adblock[${pid}]" "error logging will be disabled"
  97. fi
  98. # check dns query log configuration
  99. #
  100. if [ -n "${query_file}" ] && [ "${backup_ok}" = "true" ]
  101. then
  102. # check find capabilities
  103. #
  104. base="$(find --help 2>&1 | grep "mtime")"
  105. if [[ -z "${base}" ]]
  106. then
  107. query_ok="false"
  108. /usr/bin/logger -t "adblock[${pid}]" "no 'find/mtime' support, dns query logging will be disabled"
  109. else
  110. query_ok="true"
  111. fi
  112. else
  113. query_ok="false"
  114. /usr/bin/logger -t "adblock[${pid}]" "dns query logging will be disabled"
  115. fi
  116. # check shallalist configuration
  117. #
  118. check_shalla="$(printf "${adb_source}" | sed -n '/.*shallalist.txt.*/p')"
  119. if [ -n "${check_shalla}" ]
  120. then
  121. shalla_ok="true"
  122. else
  123. shalla_ok="false"
  124. /usr/bin/logger -t "adblock[${pid}]" "shallalist processing will be disabled"
  125. fi
  126. # check mount points & space requirements
  127. #
  128. for mp in ${mounts}
  129. do
  130. df "${mp}" 2>/dev/null |\
  131. tail -n1 |\
  132. while read filesystem overall used available scrap
  133. do
  134. av_space="${available}"
  135. if [ $((av_space)) -eq 0 ]
  136. then
  137. /usr/bin/logger -t "adblock[${pid}]" "no space left on device, not mounted (${mp})"
  138. exit 35
  139. elif [ $((av_space)) -lt $((min_space)) ]
  140. then
  141. /usr/bin/logger -t "adblock[${pid}]" "not enough space on device (${mp})"
  142. exit 40
  143. fi
  144. done
  145. # subshell return code handling
  146. #
  147. rc=$?
  148. if [ $((rc)) -ne 0 ]
  149. then
  150. f_deltemp
  151. exit ${rc}
  152. fi
  153. done
  154. # get list with all installed packages
  155. #
  156. pkg_list="$(opkg list-installed 2>/dev/null)"
  157. # check openwrt release
  158. #
  159. base="$(printf "${pkg_list}" | grep "^base-files" | sed 's/\(.*r\)//g')"
  160. if [ $((base)) -lt $((min_release)) ]
  161. then
  162. /usr/bin/logger -t "adblock[${pid}]" "openwrt (r${wrt_release}) seems to be too old"
  163. f_deltemp
  164. exit 45
  165. fi
  166. # check curl package dependency
  167. #
  168. base="$(printf "${pkg_list}" | grep "^curl")"
  169. if [ -z "${base}" ]
  170. then
  171. /usr/bin/logger -t "adblock[${pid}]" "curl package not found"
  172. f_deltemp
  173. exit 50
  174. fi
  175. # check wget package dependency
  176. #
  177. base="$(printf "${pkg_list}" | grep "^wget")"
  178. if [ -z "${base}" ]
  179. then
  180. /usr/bin/logger -t "adblock[${pid}]" "wget package not found"
  181. f_deltemp
  182. exit 55
  183. fi
  184. # check dynamic/volatile adblock network interface configuration
  185. #
  186. rc="$(ifstatus "${adb_if}" >/dev/null 2>&1; printf $?)"
  187. if [ $((rc)) -ne 0 ]
  188. then
  189. json_init
  190. json_add_string name "${adb_if}"
  191. json_add_string ifname "${adb_dev}"
  192. json_add_string proto "static"
  193. json_add_array ipaddr
  194. json_add_string "" "${adb_ip}"
  195. json_close_array
  196. json_close_object
  197. ubus call network add_dynamic "$(json_dump)"
  198. /usr/bin/logger -t "adblock[${pid}]" "created new dynamic/volatile network interface (${adb_if}, ${adb_ip})"
  199. fi
  200. # check adblock uhttpd instance configuration
  201. #
  202. if [ -z "$(uci -q get uhttpd.${adb_if} 2>/dev/null)" ]
  203. then
  204. uci -q set uhttpd.${adb_if}="uhttpd"
  205. uci -q set uhttpd.${adb_if}.listen_http="${adb_ip}:80"
  206. uci -q set uhttpd.${adb_if}.home="/www/adblock"
  207. uci -q set uhttpd.${adb_if}.error_page="/adblock.html"
  208. uci -q commit uhttpd
  209. /etc/init.d/uhttpd reload
  210. /usr/bin/logger -t "adblock[${pid}]" "created new uhttpd instance (${adb_if}, ${adb_ip}) in /etc/config/uhttpd"
  211. fi
  212. }
  213. ###################################################
  214. # f_deltemp: delete temporary files and directories
  215. f_deltemp()
  216. {
  217. if [ -f "${tmp_file}" ]
  218. then
  219. rm -f "${tmp_file}" 2>/dev/null
  220. fi
  221. if [ -d "${tmp_dir}" ]
  222. then
  223. rm -rf "${tmp_dir}" 2>/dev/null
  224. fi
  225. }
  226. ################################################################
  227. # f_remove: remove temporary files, start and maintain query log
  228. #
  229. f_remove()
  230. {
  231. # delete temporary files and directories
  232. #
  233. f_deltemp
  234. # kill existing domain query log background process,
  235. # housekeeping and start of a new process on daily basis
  236. #
  237. if [ "${query_ok}" = "true" ] && [ "${ntp_ok}" = "true" ]
  238. then
  239. query_date="$(date "+%Y%m%d")"
  240. if [ -s "${query_pid}" ] && [ ! -f "${query_file}.${query_date}" ]
  241. then
  242. kill -9 $(< "${query_pid}") 2>/dev/null
  243. > "${query_pid}"
  244. find "${backup_dir}" -maxdepth 1 -type f -mtime +${query_history} -name "${query_name}.*" -exec rm -f {} \; 2>/dev/null
  245. /usr/bin/logger -t "adblock[${pid}]" "kill old query log background process and do logfile housekeeping"
  246. fi
  247. if [ ! -s "${query_pid}" ]
  248. then
  249. ( logread -f 2>/dev/null & printf -n "$!" > "${query_pid}" ) | egrep -o "(query\[A\].*)|([a-z0-9\.\-]* is ${query_ip}$)" >> "${query_file}.${query_date}" &
  250. /usr/bin/logger -t "adblock[${pid}]" "start new domain query log background process"
  251. fi
  252. fi
  253. # final log entry
  254. #
  255. /usr/bin/logger -t "adblock[${pid}]" "domain adblock processing finished (${script_ver})"
  256. }
  257. #####################################################
  258. # f_restore: if available, restore last adlist backup
  259. #
  260. f_restore()
  261. {
  262. if [ "${backup_ok}" = "true" ] && [ -f "${backup_file}" ]
  263. then
  264. cp -f "${backup_file}" "${dns_file}" 2>/dev/null
  265. /usr/bin/logger -t "adblock[${pid}]" "${restore_msg}, adlist backup restored"
  266. printf "$(/bin/date "+%d.%m.%Y %H:%M:%S") - error: ${restore_msg}, adlist backup restored" >> "${log_file}"
  267. else
  268. > "${dns_file}"
  269. /usr/bin/logger -t "adblock[${pid}]" "${restore_msg}, empty adlist generated"
  270. printf "$(/bin/date "+%d.%m.%Y %H:%M:%S") - error: ${restore_msg}, empty adlist generated" >> "${log_file}"
  271. fi
  272. # restart dnsmasq
  273. #
  274. /etc/init.d/dnsmasq restart >/dev/null 2>&1
  275. # remove files and exit
  276. #
  277. f_remove
  278. exit 100
  279. }
  280. #######################################################
  281. # f_wancheck: check for usable adblock update interface
  282. #
  283. f_wancheck()
  284. {
  285. if [ "${wan_ok}" = "true" ]
  286. then
  287. # wait for wan update interface(s)
  288. #
  289. while [ $((cnt)) -le $((max_cnt)) ]
  290. do
  291. for dev in ${wan_dev}
  292. do
  293. dev_out=$(< /sys/class/net/${dev}/operstate 2>/dev/null)
  294. if [[ "${dev_out}" = "up" ]]
  295. then
  296. /usr/bin/logger -t "adblock[${pid}]" "get wan/update interface: ${dev}, after ${cnt} loops"
  297. break 2
  298. elif [ $((cnt)) -eq $((max_cnt)) ]
  299. then
  300. /usr/bin/logger -t "adblock[${pid}]" "no wan/update interface(s) found (${wan_dev})"
  301. printf "$(/bin/date "+%d.%m.%Y %H:%M:%S") - error: no wan/update interface(s) found (${wan_dev})" >> "${log_file}"
  302. restore_msg="no wan/update interface(s)"
  303. f_restore
  304. fi
  305. done
  306. sleep 1
  307. cnt=$((cnt + 1))
  308. done
  309. fi
  310. }
  311. #####################################
  312. # f_ntpcheck: check/get ntp time sync
  313. #
  314. f_ntpcheck()
  315. {
  316. if [ "${ntp_ok}" = "true" ]
  317. then
  318. # prepare ntp server pool
  319. #
  320. unset ntp_pool
  321. for srv in ${ntp_srv}
  322. do
  323. ntp_pool="${ntp_pool} -p ${srv}"
  324. done
  325. # wait for ntp time sync
  326. #
  327. while [ $((cnt)) -le $((max_cnt)) ]
  328. do
  329. /usr/sbin/ntpd -nq ${ntp_pool} >/dev/null 2>&1
  330. rc=$?
  331. if [ $((rc)) -eq 0 ]
  332. then
  333. /usr/bin/logger -t "adblock[${pid}]" "get ntp time sync (${ntp_srv}), after ${cnt} loops"
  334. break
  335. elif [ $((cnt)) -eq $((max_cnt)) ]
  336. then
  337. ntp_ok="false"
  338. /usr/bin/logger -t "adblock[${pid}]" "ntp time sync failed (${ntp_srv})"
  339. printf "$(/bin/date "+%d.%m.%Y %H:%M:%S") - error: ntp time sync failed (${ntp_srv})" >> "${log_file}"
  340. restore_msg="time sync failed"
  341. f_restore
  342. fi
  343. sleep 1
  344. cnt=$((cnt + 1))
  345. done
  346. fi
  347. }
  348. #################################################################
  349. # f_dnscheck: dnsmasq health check with newly generated blocklist
  350. #
  351. f_dnscheck()
  352. {
  353. # check 1: dnsmasq startup
  354. #
  355. dns_status="$(logread -l 20 -e "dnsmasq" -e "FAILED to start up")"
  356. if [ -z "${dns_status}" ]
  357. then
  358. # check 2: nslookup probe
  359. #
  360. dns_status="$(nslookup "${check_domain}" 2>/dev/null | grep "${adb_ip}")"
  361. if [ -z "${dns_status}" ]
  362. then
  363. # create backup of new block list only, if both checks are OK and backup enabled
  364. #
  365. if [ "${backup_ok}" = "true" ]
  366. then
  367. cp -f "${dns_file}" "${backup_file}" 2>/dev/null
  368. /usr/bin/logger -t "adblock[${pid}]" "new block list with ${adb_count} domains loaded, backup generated"
  369. else
  370. /usr/bin/logger -t "adblock[${pid}]" "new block list with ${adb_count} domains loaded"
  371. fi
  372. else
  373. restore_msg="nslookup probe failed"
  374. f_restore
  375. fi
  376. else
  377. restore_msg="dnsmasq probe failed"
  378. f_restore
  379. fi
  380. }
  381. ##########################################################
  382. # f_footer: write footer with a few statistics to dns file
  383. #
  384. f_footer()
  385. {
  386. # count result of merged domain entries
  387. #
  388. adb_count="$(wc -l < "${dns_file}")"
  389. # write file footer with timestamp and merged ad count sum
  390. #
  391. printf "%s\n" "###################################################" >> "${dns_file}"
  392. printf "%s\n" "# last adblock file update: $(date +"%d.%m.%Y - %T")" >> "${dns_file}"
  393. printf "%s\n" "# ${0##*/} (${script_ver}) - ${adb_count} ad/abuse domains blocked" >> "${dns_file}"
  394. printf "%s\n" "# domain blacklist sources:" >> "${dns_file}"
  395. for src in ${adb_source}
  396. do
  397. url="$(printf "${src}" | sed 's/\(\&ruleset=.*\)//g')"
  398. printf "%s\n" "# ${url}" >> "${dns_file}"
  399. done
  400. printf "%s\n" "###################################################" >> "${dns_file}"
  401. printf "%s\n" "# domain whitelist source:" >> "${dns_file}"
  402. printf "%s\n" "# ${adb_whitelist}" >> "${dns_file}"
  403. printf "%s\n" "###################################################" >> "${dns_file}"
  404. }