2 ##############################################
3 # function library used by adblock-update.sh #
4 # written by Dirk Brenken (dirk@brenken.org) #
5 ##############################################
7 #####################################
8 # f_envload: load adblock environment
12 # source in openwrt function library
14 if [ -r "/lib/functions.sh" ]
18 /usr
/bin
/logger
-t "adblock[${pid}]" "error: openwrt function library not found"
23 # source in openwrt json helpers library
25 if [ -r "/usr/share/libubox/jshn.sh" ]
27 .
"/usr/share/libubox/jshn.sh"
29 /usr
/bin
/logger
-t "adblock[${pid}]" "error: openwrt json helpers library not found"
34 # get list with all installed openwrt packages
36 pkg_list
="$(opkg list-installed 2>/dev/null)"
37 if [ -z "${pkg_list}" ]
39 /usr
/bin
/logger
-t "adblock[${pid}]" "error: empty openwrt package list"
45 ######################################################
46 # f_envparse: parse adblock config and set environment
50 # function to read/set global options by callback,
51 # prepare list items and build option list for all others
57 if [ "${type}" = "adblock" ]
63 eval "${option}=\"${value}\""
70 local opt_out
="$(printf "${option}" | sed -n '/.*_ITEM[0-9]$/p; /.*_LENGTH$/p; /enabled/p')"
71 if [ -z "${opt_out}" ]
73 all_options
="${all_options} ${option}"
80 if [ "${list}" = "adb_wanlist" ]
82 adb_wandev
="${adb_wandev} ${value}"
83 elif [ "${list}" = "adb_ntplist" ]
85 adb_ntpsrv
="${adb_ntpsrv} ${value}"
86 elif [ "${list}" = "adb_catlist" ]
88 adb_cat_shalla
="${adb_cat_shalla} ${value}"
94 # function to iterate through option list, read/set all options in "enabled" sections
99 config_get switch
"${config}" "enabled"
100 if [ "${switch}" = "1" ]
102 for option
in ${all_options}
104 config_get value
"${config}" "${option}"
107 local opt_src
="$(printf "${option}" | sed -n '/^adb_src_[a-z0-9]*$/p')"
108 if [ -n "${opt_src}" ]
110 adb_sources
="${adb_sources} ${value}"
112 eval "${option}=\"${value}\""
116 elif [ "${config}" = "wancheck" ]
119 elif [ "${config}" = "ntpcheck" ]
122 elif [ "${config}" = "shalla" ]
128 # load adblock config and start parsing functions
131 config_foreach parse_config service
132 config_foreach parse_config
source
134 # set temp variables and counter
136 adb_tmpfile
="$(mktemp -tu)"
137 adb_tmpdir
="$(mktemp -d)"
142 # set adblock source ruleset definitions
144 rset_start
="sed -r 's/[[:space:]]|[\[!#/:;_].*|[0-9\.]*localhost//g; s/[\^#/:;_\.\t ]*$//g'"
145 rset_end
="sed '/^[#/:;_\s]*$/d'"
146 rset_default
="${rset_start} | ${rset_end}"
147 rset_yoyo
="${rset_start} | sed 's/,/\n/g' | ${rset_end}"
148 rset_shalla
="${rset_start} | sed 's/\([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}$//g' | ${rset_end}"
149 rset_spam404
="${rset_start} | sed 's/^\|\|//g' | ${rset_end}"
150 rset_winhelp
="${rset_start} | sed 's/\([0-9]\{1,3\}\.\)\{3\}[0-1]\{1,1\}//g' | ${rset_end}"
152 # set adblock/dnsmasq destination file and format
154 adb_dnsfile
="/tmp/dnsmasq.d/adlist.conf"
155 adb_dnsformat
="sed 's/^/address=\//;s/$/\/'${adb_ip}'/'"
158 #############################################
159 # f_envcheck: check environment prerequisites
163 # check adblock network device configuration
165 if [ ! -d "/sys/class/net/${adb_dev}" ]
167 /usr
/bin
/logger
-t "adblock[${pid}]" "error: invalid adblock network device input (${adb_dev})"
172 # check adblock network interface configuration
174 check_if
="$(printf "${adb_if}" | sed -n '/[^_0-9A-Za-z]/p')"
175 banned_if
="$(printf "${adb_if}" | sed -n '/.*lan.*\|.*wan.*\|.*switch.*\|main\|globals\|loopback\|px5g/p')"
176 if [ -n "${check_if}" ] ||
[ -n "${banned_if}" ]
178 /usr
/bin
/logger
-t "adblock[${pid}]" "error: invalid adblock network interface input (${adb_if})"
183 # check adblock ip address configuration
185 check_ip
="$(printf "${adb_ip}" | sed -n '/\([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}/p')"
186 if [ -z "${check_ip}" ]
188 /usr
/bin
/logger
-t "adblock[${pid}]" "error: invalid adblock ip address input (${adb_ip})"
193 # check adblock blacklist/whitelist configuration
195 if [ ! -r "${adb_blacklist}" ]
197 /usr
/bin
/logger
-t "adblock[${pid}]" "error: adblock blacklist not found"
200 elif [ ! -r "${adb_whitelist}" ]
202 /usr
/bin
/logger
-t "adblock[${pid}]" "error: adblock whitelist not found"
207 # check wan update configuration
209 if [ -n "${adb_wandev}" ]
214 /usr
/bin
/logger
-t "adblock[${pid}]" "info: wan update check will be disabled"
217 # check ntp sync configuration
219 if [ -n "${adb_ntpsrv}" ]
224 /usr
/bin
/logger
-t "adblock[${pid}]" "info: ntp time sync will be disabled"
227 # check backup configuration
229 adb_backupdir
="${adb_backupfile%/*}"
230 if [ -n "${adb_backupdir}" ] && [ -d "${adb_backupdir}" ]
233 adb_mounts
="${adb_backupdir} ${adb_tmpdir}"
236 /usr
/bin
/logger
-t "adblock[${pid}]" "info: backup/restore will be disabled"
239 # check error log configuration
241 adb_logdir
="${adb_logfile%/*}"
242 if [ -n "${adb_logfile}" ] && [ "${adb_logfile}" = "/dev/stdout" ]
245 adb_logfile
="/proc/self/fd/1"
246 elif [ -n "${adb_logdir}" ] && [ -d "${adb_logdir}" ] && [ "${ntp_ok}" = "true" ]
249 adb_mounts
="${adb_mounts} ${adb_logdir}"
252 adb_logfile
="/dev/null"
253 /usr
/bin
/logger
-t "adblock[${pid}]" "info: error logging will be disabled"
256 # check dns query log configuration
258 adb_querydir
="${adb_queryfile%/*}"
259 if [ -n "${adb_querydir}" ] && [ -d "${adb_querydir}" ]
261 # check find capabilities
263 check
="$(find --help 2>&1 | grep "mtime
")"
267 /usr
/bin
/logger
-t "adblock[${pid}]" "info: busybox without 'find/mtime' support (min. r47362), dns query logging will be disabled"
270 query_name
="${adb_queryfile##*/}"
271 query_ip
="${adb_ip//./\\.}"
272 query_pid
="/var/run/query.pid"
273 adb_mounts
="${adb_mounts} ${adb_querydir}"
277 /usr
/bin
/logger
-t "adblock[${pid}]" "info: dns query logging will be disabled"
280 # check mount points & space requirements
282 adb_mounts
="${adb_mounts} ${adb_tmpdir}"
283 for mp
in ${adb_mounts}
285 df
"${mp}" 2>/dev
/null |\
287 while read filesystem overall used available scrap
289 av_space
="${available}"
290 if [ $
((av_space
)) -eq 0 ]
292 /usr
/bin
/logger
-t "adblock[${pid}]" "error: no space left on device/not mounted (${mp})"
294 elif [ $
((av_space
)) -lt $
((adb_minspace
)) ]
296 /usr
/bin
/logger
-t "adblock[${pid}]" "error: not enough space on device (${mp})"
300 # subshell return code handling
310 # check curl package dependency
312 check
="$(printf "${pkg_list}" | grep "^curl
")"
315 /usr
/bin
/logger
-t "adblock[${pid}]" "error: curl package not found"
320 # check wget package dependency
322 check
="$(printf "${pkg_list}" | grep "^wget
")"
325 /usr
/bin
/logger
-t "adblock[${pid}]" "error: wget package not found"
330 # check dynamic/volatile adblock network interface configuration
332 rc
="$(ifstatus "${adb_if}" >/dev/null 2>&1; printf $?)"
336 json_add_string name
"${adb_if}"
337 json_add_string ifname
"${adb_dev}"
338 json_add_string proto
"static"
339 json_add_array ipaddr
340 json_add_string
"" "${adb_ip}"
343 ubus call network add_dynamic
"$(json_dump)"
344 /usr
/bin
/logger
-t "adblock[${pid}]" "info: created new dynamic/volatile network interface (${adb_if}, ${adb_ip})"
347 # check dynamic/volatile adblock uhttpd instance configuration
349 rc
="$(ps | grep "[u
]httpd.
*\
-r ${adb_if}" >/dev/null 2>&1; printf $?)"
352 uhttpd
-h "/www/adblock" -r "${adb_if}" -E "/adblock.html" -p "${adb_ip}:80"
353 /usr
/bin
/logger
-t "adblock[${pid}]" "info: created new dynamic/volatile uhttpd instance (${adb_if}, ${adb_ip})"
357 ###################################################
358 # f_deltemp: delete temporary files and directories
362 if [ -f "${adb_tmpfile}" ]
364 rm -f "${adb_tmpfile}" 2>/dev
/null
366 if [ -d "${adb_tmpdir}" ]
368 rm -rf "${adb_tmpdir}" 2>/dev
/null
372 ################################################################
373 # f_remove: remove temporary files, start and maintain query log
377 # delete temporary files and directories
381 # kill existing domain query log background process,
382 # housekeeping and start of a new process on daily basis
384 if [ "${query_ok}" = "true" ] && [ "${ntp_ok}" = "true" ]
386 query_date
="$(date "+%Y
%m
%d
")"
387 if [ -s "${query_pid}" ] && [ ! -f "${adb_queryfile}.${query_date}" ]
389 kill -9 $
(< "${query_pid}") 2>/dev
/null
391 find "${adb_backupdir}" -maxdepth 1 -type f -mtime +${adb_queryhistory} -name "${query_name}.*" -exec rm -f {} \; 2>/dev/null
392 /usr/bin/logger -t "adblock
[${pid}]" "info
: kill old query log background process and
do logfile housekeeping
"
394 if [ ! -s "${query_pid}" ]
396 ( logread -f 2>/dev/null & printf -n "$
!" > "${query_pid}" ) | egrep -o "(query\[A\].*)|([a-z0-9\.\-]* is ${query_ip}$)" >> "${adb_queryfile}.${query_date}" &
397 /usr/bin/logger -t "adblock
[${pid}]" "info
: start new domain query log background process
"
403 /usr/bin/logger -t "adblock
[${pid}]" "info
: domain adblock processing finished
(${adb_version})"
406 #####################################################
407 # f_restore: if available, restore last adlist backup
411 if [ -z "${restore_msg}" ]
413 restore_msg="unknown
"
416 if [ "${backup_ok}" = "true
" ] && [ -f "${adb_backupfile}" ]
418 cp -f "${adb_backupfile}" "${adb_dnsfile}" 2>/dev/null
419 /usr/bin/logger -t "adblock
[${pid}]" "error
: ${restore_msg}, adlist backup restored
"
420 printf "$
(/bin
/date "+%d.%m.%Y %H:%M:%S") - error
: ${restore_msg}, adlist backup restored
" >> "${adb_logfile}"
423 /usr/bin/logger -t "adblock
[${pid}]" "error
: ${restore_msg}, empty adlist generated
"
424 printf "$
(/bin
/date "+%d.%m.%Y %H:%M:%S") - error
: ${restore_msg}, empty adlist generated
" >> "${adb_logfile}"
429 /etc/init.d/dnsmasq restart >/dev/null 2>&1
431 # remove files and exit
437 #######################################################
438 # f_wancheck: check for usable adblock update interface
442 if [ "${wan_ok}" = "true
" ]
444 # wait for wan update interface(s)
446 while [ $((cnt)) -le $((max_cnt)) ]
448 for dev in ${adb_wandev}
450 if [ -d "/sys
/class
/net
/${dev}" ]
452 dev_out=$(< /sys/class/net/${dev}/operstate 2>/dev/null)
453 if [ "${dev_out}" = "up
" ]
455 /usr/bin/logger -t "adblock
[${pid}]" "info: get wan/update interface: ${dev}, after ${cnt} loops
"
459 if [ $((cnt)) -eq $((max_cnt)) ]
461 /usr/bin/logger -t "adblock
[${pid}]" "error
: no wan
/update interface
(s
) found
(${adb_wandev})"
462 printf "$
(/bin
/date "+%d.%m.%Y %H:%M:%S") - error
: no wan
/update interface
(s
) found
(${adb_wandev})" >> "${adb_logfile}"
463 restore_msg="no wan
/update interface
(s
)"
473 #####################################
474 # f_ntpcheck: check/get ntp time sync
478 if [ "${ntp_ok}" = "true
" ]
480 # prepare ntp server pool
483 for srv in ${adb_ntpsrv}
485 ntp_pool="${ntp_pool} -p ${srv}"
488 # wait for ntp time sync
490 while [ $((cnt)) -le $((max_cnt)) ]
492 /usr/sbin/ntpd -nq ${ntp_pool} >/dev/null 2>&1
496 /usr/bin/logger -t "adblock
[${pid}]" "info: get ntp time sync (${adb_ntpsrv}), after ${cnt} loops
"
499 if [ $((cnt)) -eq $((max_cnt)) ]
502 /usr/bin/logger -t "adblock
[${pid}]" "error
: ntp
time sync failed
(${adb_ntpsrv})"
503 printf "$
(/bin
/date "+%d.%m.%Y %H:%M:%S") - error
: ntp
time sync failed
(${adb_ntpsrv})" >> "${adb_logfile}"
504 restore_msg="time sync failed
"
513 #################################################################
514 # f_dnscheck: dnsmasq health check with newly generated blocklist
518 # check 1: dnsmasq startup
520 dns_status="$
(logread
-l 20 -e "dnsmasq" -e "FAILED to start up")"
521 if [ -z "${dns_status}" ]
523 # check 2: nslookup probe
525 dns_status="$
(nslookup "${adb_domain}" 2>/dev
/null |
grep "${adb_ip}")"
526 if [ -z "${dns_status}" ]
528 # create backup of new block list only, if both checks are OK and backup enabled
530 if [ "${backup_ok}" = "true
" ]
532 cp -f "${adb_dnsfile}" "${adb_backupfile}" 2>/dev/null
533 /usr/bin/logger -t "adblock
[${pid}]" "info
: new block list with
${adb_count} domains loaded
, backup generated
"
535 /usr/bin/logger -t "adblock
[${pid}]" "info
: new block list with
${adb_count} domains loaded
, no backup
"
538 restore_msg="nslookup probe failed
"
542 restore_msg="dnsmasq probe failed
"
547 ##########################################################
548 # f_footer: write footer with a few statistics to dns file
552 adb_count="$
(wc -l < "${adb_dnsfile}")"
553 printf "%s
\n" "###################################################" >> "${adb_dnsfile}"
554 printf "%s\n" "# last adblock file update: $(date +"%d.
%m.
%Y
- %T
")" >> "${adb_dnsfile}"
555 printf "%s\n" "# ${0##*/} (${adb_version}) - ${adb_count} ad/abuse domains blocked" >> "${adb_dnsfile}"
556 printf "%s\n" "# domain blacklist sources:" >> "${adb_dnsfile}"
557 for src
in ${adb_sources}
559 url
="${src//\&ruleset=*/}"
560 printf "%s\n" "# ${url}" >> "${adb_dnsfile}"
562 printf "%s\n" "###################################################" >> "${adb_dnsfile}"
563 printf "%s\n" "# domain whitelist source:" >> "${adb_dnsfile}"
564 printf "%s\n" "# ${adb_whitelist}" >> "${adb_dnsfile}"
565 printf "%s\n" "###################################################" >> "${adb_dnsfile}"