adblock: 0.70.1
[feed/packages.git] / net / adblock / files / adblock-helper.sh
1 #!/bin/sh
2 #################################################
3 # function library used by adblock-update.sh #
4 # written by Dirk Brenken (openwrt@brenken.org) #
5 #################################################
6
7 #####################################
8 # f_envload: load adblock environment
9 #
10 f_envload()
11 {
12 local cfg_version
13
14 # get version string from default adblock configuration file
15 #
16 cfg_version="$(/sbin/uci -q get adblock.global.adb_cfgver 2>/dev/null)"
17 cfg_enabled="$(/sbin/uci -q get adblock.global.adb_enabled 2>/dev/null)"
18 rc=$?
19 if [ $((rc)) -ne 0 ] || [ "${cfg_version}" != "${adb_scriptver%.*}" ]
20 then
21 cp -pf "/etc/adblock/adblock.conf.default" "/etc/config/adblock" >/dev/null 2>&1
22 rc=$?
23 if [ $((rc)) -eq 0 ]
24 then
25 f_log "new default adblock configuration applied, please check your settings in '/etc/config/adblock'"
26 else
27 f_log "original adblock configuration not found, please (re-)install the adblock package via 'opkg install adblock --force-maintainer'" "${rc}"
28 f_exit
29 fi
30 elif [ $((rc)) -eq 0 ] && [ $((cfg_enabled)) -ne 1 ]
31 then
32 rc=-1
33 f_log "adblock is currently disabled, please run 'uci set adblock.global.adb_enabled=1' and 'uci commit adblock' to enable this service"
34 f_exit
35 fi
36
37 # source in openwrt function library
38 #
39 if [ -r "/lib/functions.sh" ]
40 then
41 . "/lib/functions.sh" 2>/dev/null
42 else
43 rc=110
44 f_log "openwrt function library not found" "${rc}"
45 f_exit
46 fi
47
48 # source in openwrt network library
49 #
50 if [ -r "/lib/functions/network.sh" ]
51 then
52 . "/lib/functions/network.sh" 2>/dev/null
53 else
54 rc=115
55 f_log "openwrt network library not found" "${rc}"
56 f_exit
57 fi
58
59 # check opkg availability and get list with all installed openwrt packages
60 #
61 if [ -r "/var/lock/opkg.lock" ]
62 then
63 rc=-1
64 f_log "adblock installation finished, 'opkg' currently locked by package installer"
65 f_exit
66 fi
67 pkg_list="$(opkg list-installed 2>/dev/null)"
68 if [ -z "${pkg_list}" ]
69 then
70 rc=120
71 f_log "empty openwrt package list" "${rc}"
72 f_exit
73 fi
74 }
75
76 ######################################################
77 # f_envparse: parse adblock config and set environment
78 #
79 f_envparse()
80 {
81 # set initial defaults,
82 # may be overwritten by setting appropriate adblock config options in global section of /etc/config/adblock
83 #
84 adb_wanif="wan"
85 adb_lanif="lan"
86 adb_port="65535"
87 adb_nullipv4="192.0.2.1"
88 adb_nullipv6="::ffff:c000:0201"
89 adb_maxtime="60"
90 adb_maxloop="20"
91 adb_blacklist="/etc/adblock/adblock.blacklist"
92 adb_whitelist="/etc/adblock/adblock.whitelist"
93
94 # function to read/set global options by callback,
95 # prepare list items and build option list for all others
96 #
97 config_cb()
98 {
99 local type="${1}"
100 local name="${2}"
101 if [ "${type}" = "adblock" ]
102 then
103 option_cb()
104 {
105 local option="${1}"
106 local value="${2}"
107 eval "${option}=\"${value}\""
108 }
109 else
110 option_cb()
111 {
112 local option="${1}"
113 local value="${2}"
114 local opt_out="$(printf "${option}" | sed -n '/.*_ITEM[0-9]$/p; /.*_LENGTH$/p; /enabled/p' 2>/dev/null)"
115 if [ -z "${opt_out}" ]
116 then
117 all_options="${all_options} ${option}"
118 fi
119 }
120 list_cb()
121 {
122 local list="${1}"
123 local value="${2}"
124 if [ "${list}" = "adb_catlist" ]
125 then
126 adb_cat_shalla="${adb_cat_shalla} ${value}"
127 fi
128 }
129 fi
130 }
131
132 # function to iterate through option list, read/set all options in "enabled" sections
133 #
134 parse_config()
135 {
136 local config="${1}"
137 config_get switch "${config}" "enabled"
138 if [ "${switch}" = "1" ]
139 then
140 for option in ${all_options}
141 do
142 config_get value "${config}" "${option}"
143 if [ -n "${value}" ]
144 then
145 local opt_src="$(printf "${option}" | sed -n '/^adb_src_[a-z0-9]*$/p' 2>/dev/null)"
146 if [ -n "${opt_src}" ]
147 then
148 adb_sources="${adb_sources} ${value}"
149 else
150 eval "${option}=\"${value}\""
151 fi
152 fi
153 done
154 fi
155 }
156
157 # load adblock config and start parsing functions
158 #
159 config_load adblock
160 config_foreach parse_config service
161 config_foreach parse_config source
162
163 # set more script defaults (can't be overwritten by adblock config options)
164 #
165 adb_cnt=0
166 adb_minspace=20000
167 adb_unique=1
168 adb_tmpfile="$(mktemp -tu 2>/dev/null)"
169 adb_tmpdir="$(mktemp -p /tmp -d 2>/dev/null)"
170 adb_dnsdir="/tmp/dnsmasq.d"
171 adb_dnsprefix="adb_list"
172 adb_prechain_ipv4="prerouting_rule"
173 adb_fwdchain_ipv4="forwarding_rule"
174 adb_outchain_ipv4="output_rule"
175 adb_prechain_ipv6="PREROUTING"
176 adb_fwdchain_ipv6="forwarding_rule"
177 adb_outchain_ipv6="output_rule"
178 adb_fetch="/usr/bin/wget"
179 unset adb_srclist
180 unset adb_revsrclist
181 unset adb_errsrclist
182
183 # set adblock source ruleset definitions
184 #
185 rset_start="sed -r 's/[[:space:]]|[\[!#/:;_].*|[0-9\.]*localhost.*//g; s/[\^#/:;_\.\t ]*$//g'"
186 rset_end="tr -cd '[0-9a-z\.\-]\n' | sed -r 's/^[ \.\-].*$|^[a-z0-9]*[ \.\-]*$//g; /^[#/:;_\s]*$/d'"
187 rset_adaway="${rset_start} | sed 's/\([0-9]\{1,3\}\.\)\{3\}[0-1]\{1,1\}//g' | ${rset_end}"
188 rset_blacklist="${rset_start} | ${rset_end}"
189 rset_disconnect="${rset_start} | ${rset_end}"
190 rset_dshield="${rset_start} | ${rset_end}"
191 rset_feodo="${rset_start} | ${rset_end}"
192 rset_malware="${rset_start} | ${rset_end}"
193 rset_malwarelist="${rset_start} | sed 's/\([0-9]\{1,3\}\.\)\{3\}[0-1]\{1,1\}//g' | ${rset_end}"
194 rset_openphish="sed -e 's|^[^/]*//||' -e 's|/.*$||'"
195 rset_palevo="${rset_start} | ${rset_end}"
196 rset_ruadlist="sed -e '/^\|\|/! s/.*//; /\^$/! s/.*//; s/\^$//g; /[\.]/! s/.*//; s/^[\|]\{1,2\}//g' | ${rset_end}"
197 rset_shalla="${rset_start} | sed 's/\([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}$//g' | ${rset_end}"
198 rset_spam404="${rset_start} | sed 's/^\|\|//g' | ${rset_end}"
199 rset_whocares="${rset_start} | sed 's/\([0-9]\{1,3\}\.\)\{3\}[0-1]\{1,1\}//g' | ${rset_end}"
200 rset_winhelp="${rset_start} | sed 's/\([0-9]\{1,3\}\.\)\{3\}[0-1]\{1,1\}//g' | ${rset_end}"
201 rset_yoyo="${rset_start} | sed 's/,/\n/g' | ${rset_end}"
202 rset_zeus="${rset_start} | ${rset_end}"
203
204 # get logical wan update interfaces (with default route) and their device names
205 #
206 while [ $((adb_cnt)) -le $((adb_maxloop)) ]
207 do
208 network_find_wan adb_wanif4 2>/dev/null
209 network_find_wan6 adb_wanif6 2>/dev/null
210 if [ -z "${adb_wanif4}" ] && [ -z "${adb_wanif6}" ]
211 then
212 network_flush_cache
213 elif [ "${adb_wanif4}" = "${adb_lanif}" ] || [ "${adb_wanif6}" = "${adb_lanif}" ]
214 then
215 rc=125
216 f_log "LAN only (${adb_lanif}) network, no valid IPv4/IPv6 wan update interface found" "${rc}"
217 f_exit
218 else
219 network_get_device adb_wandev4 "${adb_wanif4}" 2>/dev/null
220 network_get_device adb_wandev6 "${adb_wanif6}" 2>/dev/null
221 break
222 fi
223 if [ $((adb_cnt)) -ge $((adb_maxloop)) ]
224 then
225 rc=125
226 f_log "no valid IPv4/IPv6 wan update interface found" "${rc}"
227 f_exit
228 fi
229 adb_cnt=$((adb_cnt + 1))
230 sleep 1
231 done
232
233 # get lan ip addresses
234 #
235 network_get_ipaddr adb_ipv4 "${adb_lanif}" 2>/dev/null
236 network_get_ipaddr6 adb_ipv6 "${adb_lanif}" 2>/dev/null
237 if [ -z "${adb_ipv4}" ] && [ -z "${adb_ipv6}" ]
238 then
239 rc=130
240 f_log "no valid IPv4/IPv6 configuration for given logical LAN interface found (${adb_lanif}), please set 'adb_lanif' manually" "${rc}"
241 f_exit
242 fi
243
244 # read system ntp server names
245 #
246 adb_ntpsrv="$(uci get system.ntp.server 2>/dev/null)"
247 }
248
249 #################################################
250 # f_envcheck: check/set environment prerequisites
251 #
252 f_envcheck()
253 {
254 local check
255
256 # check general package dependencies
257 #
258 f_depend "uhttpd"
259 f_depend "wget"
260 f_depend "iptables"
261 f_depend "kmod-ipt-nat"
262
263 # check ipv6 related package dependencies
264 #
265 if [ -n "${adb_wanif6}" ]
266 then
267 check="$(printf "${pkg_list}" | grep "^ip6tables -" 2>/dev/null)"
268 if [ -z "${check}" ]
269 then
270 f_log "package 'ip6tables' not found, IPv6 support wíll be disabled"
271 unset adb_wanif6
272 else
273 check="$(printf "${pkg_list}" | grep "^kmod-ipt-nat6 -" 2>/dev/null)"
274 if [ -z "${check}" ]
275 then
276 f_log "package 'kmod-ipt-nat6' not found, IPv6 support wíll be disabled"
277 unset adb_wanif6
278 fi
279 fi
280 fi
281
282 # check ca-certificates package and set wget parms accordingly
283 #
284 check="$(printf "${pkg_list}" | grep "^ca-certificates -" 2>/dev/null)"
285 if [ -z "${check}" ]
286 then
287 wget_parm="--no-config --no-check-certificate --quiet --tries=1 --no-cache --no-cookies --max-redirect=0 --dns-timeout=5"
288 else
289 wget_parm="--no-config --quiet --tries=1 --no-cache --no-cookies --max-redirect=0 --dns-timeout=5"
290 fi
291
292 # check adblock blacklist/whitelist configuration
293 #
294 if [ ! -r "${adb_blacklist}" ]
295 then
296 rc=135
297 f_log "adblock blacklist not found (${adb_blacklist})" "${rc}"
298 f_exit
299 elif [ ! -r "${adb_whitelist}" ]
300 then
301 rc=135
302 f_log "adblock whitelist not found (${adb_whitelist})" "${rc}"
303 f_exit
304 fi
305
306 # check adblock temp directory
307 #
308 if [ -n "${adb_tmpdir}" ] && [ -d "${adb_tmpdir}" ]
309 then
310 f_space "${adb_tmpdir}"
311 if [ "${space_ok}" = "false" ]
312 then
313 rc=140
314 f_log "not enough space in '${adb_tmpdir}', please supersize your temp directory" "${rc}"
315 f_exit
316 fi
317 else
318 rc=140
319 f_log "temp directory not found" "${rc}"
320 f_exit
321 fi
322
323 # check total and swap memory
324 #
325 mem_total="$(grep -F "MemTotal" "/proc/meminfo" 2>/dev/null | grep -o "[0-9]*" 2>/dev/null)"
326 mem_free="$(grep -F "MemFree" "/proc/meminfo" 2>/dev/null | grep -o "[0-9]*" 2>/dev/null)"
327 swap_total="$(grep -F "SwapTotal" "/proc/meminfo" 2>/dev/null | grep -o "[0-9]*" 2>/dev/null)"
328 if [ $((mem_total)) -le 64000 ] && [ $((swap_total)) -eq 0 ]
329 then
330 adb_unique=0
331 f_log "not enough memory, overall sort/unique processing will be disabled"
332 f_log "please consider adding an external swap device to supersize your temp directory (total: ${mem_total}, free: ${mem_free}, swap: ${mem_swap})"
333 fi
334
335 # check backup configuration
336 #
337 if [ -n "${adb_backupdir}" ] && [ -d "${adb_backupdir}" ]
338 then
339 f_space "${adb_backupdir}"
340 if [ "${space_ok}" = "false" ]
341 then
342 f_log "not enough space in '${adb_backupdir}', backup/restore will be disabled"
343 backup_ok="false"
344 else
345 f_log "backup/restore will be enabled"
346 backup_ok="true"
347 fi
348 else
349 backup_ok="false"
350 f_log "backup/restore will be disabled"
351 fi
352
353 # check log configuration
354 #
355 adb_logdir="${adb_logfile%/*}"
356 if [ -n "${adb_logdir}" ] && [ -d "${adb_logdir}" ]
357 then
358 f_space "${adb_logdir}"
359 if [ "${space_ok}" = "false" ]
360 then
361 f_log "not enough space in '${adb_logdir}', logging will be disabled"
362 log_ok="false"
363 else
364 f_log "logging will be enabled"
365 log_ok="true"
366 fi
367 else
368 log_ok="false"
369 f_log "logging will be disabled"
370 fi
371
372 # check ipv4/iptables configuration
373 #
374 if [ -n "${adb_wanif4}" ] && [ -n "${adb_wandev4}" ]
375 then
376 f_firewall "IPv4" "nat" "A" "${adb_prechain_ipv4}" "adb-prerouting" "! -i ${adb_wandev4} -p tcp -d ${adb_nullipv4} -m multiport --dports 80,443 -j REDIRECT --to-ports ${adb_port}"
377 f_firewall "IPv4" "nat" "A" "${adb_prechain_ipv4}" "adb-dns" "! -i ${adb_wandev4} -p udp --dport 53 -j REDIRECT"
378 f_firewall "IPv4" "nat" "A" "${adb_prechain_ipv4}" "adb-dns" "! -i ${adb_wandev4} -p tcp --dport 53 -j REDIRECT"
379 f_firewall "IPv4" "filter" "A" "${adb_fwdchain_ipv4}" "adb-forward" "! -i ${adb_wandev4} -p udp -d ${adb_nullipv4} -j REJECT --reject-with icmp-port-unreachable"
380 f_firewall "IPv4" "filter" "A" "${adb_fwdchain_ipv4}" "adb-forward" "! -i ${adb_wandev4} -p tcp -d ${adb_nullipv4} -j REJECT --reject-with tcp-reset"
381 f_firewall "IPv4" "filter" "A" "${adb_fwdchain_ipv4}" "adb-forward" "! -i ${adb_wandev4} -d ${adb_nullipv4} -j REJECT --reject-with icmp-proto-unreachable"
382 f_firewall "IPv4" "filter" "A" "${adb_outchain_ipv4}" "adb-output" "! -i ${adb_wandev4} -p udp -d ${adb_nullipv4} -j REJECT --reject-with icmp-port-unreachable"
383 f_firewall "IPv4" "filter" "A" "${adb_outchain_ipv4}" "adb-output" "! -i ${adb_wandev4} -p tcp -d ${adb_nullipv4} -j REJECT --reject-with tcp-reset"
384 f_firewall "IPv4" "filter" "A" "${adb_outchain_ipv4}" "adb-output" "! -i ${adb_wandev4} -d ${adb_nullipv4} -j REJECT --reject-with icmp-proto-unreachable"
385 if [ "${fw_done}" = "true" ]
386 then
387 f_log "created volatile IPv4 firewall ruleset"
388 fw_done="false"
389 fi
390 fi
391
392 # check ipv6/ip6tables configuration
393 #
394 if [ -n "${adb_wanif6}" ] && [ -n "${adb_wandev6}" ]
395 then
396 f_firewall "IPv6" "nat" "A" "${adb_prechain_ipv6}" "adb-prerouting" "! -i ${adb_wandev6} -p tcp -d ${adb_nullipv6} -m multiport --dports 80,443 -j REDIRECT --to-ports ${adb_port}"
397 f_firewall "IPv6" "nat" "A" "${adb_prechain_ipv6}" "adb-dns" "! -i ${adb_wandev6} -p udp --dport 53 -j REDIRECT"
398 f_firewall "IPv6" "nat" "A" "${adb_prechain_ipv6}" "adb-dns" "! -i ${adb_wandev6} -p tcp --dport 53 -j REDIRECT"
399 f_firewall "IPv6" "filter" "A" "${adb_fwdchain_ipv6}" "adb-forward" "! -i ${adb_wandev6} -p udp -d ${adb_nullipv6} -j REJECT --reject-with icmp-port-unreachable"
400 f_firewall "IPv6" "filter" "A" "${adb_fwdchain_ipv6}" "adb-forward" "! -i ${adb_wandev6} -p tcp -d ${adb_nullipv6} -j REJECT --reject-with tcp-reset"
401 f_firewall "IPv6" "filter" "A" "${adb_fwdchain_ipv6}" "adb-forward" "! -i ${adb_wandev6} -d ${adb_nullipv6} -j REJECT --reject-with icmp-proto-unreachable"
402 f_firewall "IPv6" "filter" "A" "${adb_outchain_ipv6}" "adb-output" "! -i ${adb_wandev6} -p udp -d ${adb_nullipv6} -j REJECT --reject-with icmp-port-unreachable"
403 f_firewall "IPv6" "filter" "A" "${adb_outchain_ipv6}" "adb-output" "! -i ${adb_wandev6} -p tcp -d ${adb_nullipv6} -j REJECT --reject-with tcp-reset"
404 f_firewall "IPv6" "filter" "A" "${adb_outchain_ipv6}" "adb-output" "! -i ${adb_wandev6} -d ${adb_nullipv6} -j REJECT --reject-with icmp-proto-unreachable"
405 if [ "${fw_done}" = "true" ]
406 then
407 f_log "created volatile IPv6 firewall ruleset"
408 fw_done="false"
409 fi
410 fi
411
412 # check volatile adblock uhttpd instance configuration
413 #
414 rc="$(ps | grep "[u]httpd.*\-h /www/adblock" >/dev/null 2>&1; printf ${?})"
415 if [ $((rc)) -ne 0 ]
416 then
417 if [ -n "${adb_wanif4}" ] && [ -n "${adb_wanif6}" ]
418 then
419 uhttpd -h "/www/adblock" -k 5 -N 200 -t 0 -T 1 -D -S -E "/adblock.html" -p "${adb_ipv4}:${adb_port}" -p "[${adb_ipv6}]:${adb_port}">/dev/null 2>&1
420 rc=${?}
421 if [ $((rc)) -eq 0 ]
422 then
423 f_log "created volatile uhttpd instance (${adb_ipv4}:${adb_port}, [${adb_ipv6}]:${adb_port})"
424 else
425 f_log "failed to initialize volatile uhttpd instance (${adb_ipv4}:${adb_port}, [${adb_ipv6}]:${adb_port})" "${rc}"
426 f_restore
427 fi
428 elif [ -n "${adb_wanif4}" ]
429 then
430 uhttpd -h "/www/adblock" -k 5 -N 200 -t 0 -T 1 -D -S -E "/adblock.html" -p "${adb_ipv4}:${adb_port}" >/dev/null 2>&1
431 rc=${?}
432 if [ $((rc)) -eq 0 ]
433 then
434 f_log "created volatile uhttpd instance (${adb_ipv4}:${adb_port})"
435 else
436 f_log "failed to initialize volatile uhttpd instance (${adb_ipv4}:${adb_port})" "${rc}"
437 f_restore
438 fi
439 elif [ -n "${adb_wanif6}" ]
440 then
441 uhttpd -h "/www/adblock" -k 5 -N 200 -t 0 -T 1 -D -S -E "/adblock.html" -p "[${adb_ipv6}]:${adb_port}" >/dev/null 2>&1
442 rc=${?}
443 if [ $((rc)) -eq 0 ]
444 then
445 f_log "created volatile uhttpd instance ([${adb_ipv6}]:${adb_port})"
446 else
447 f_log "failed to initialize volatile uhttpd instance ([${adb_ipv6}]:${adb_port})" "${rc}"
448 f_restore
449 fi
450 fi
451 fi
452
453 # wait for active wan update interface
454 #
455 while [ $((adb_cnt)) -le $((adb_maxloop)) ]
456 do
457 for interface in ${adb_wanif}
458 do
459 network_get_device adb_wandev "${interface}" 2>/dev/null
460 if [ -z "${adb_wandev}" ] || [ ! -d "/sys/class/net/${adb_wandev}" ]
461 then
462 if [ -n "${adb_wandev4}" ]
463 then
464 adb_wandev="${adb_wandev4}"
465 else
466 adb_wandev="${adb_wandev6}"
467 fi
468 if [ -z "${adb_wandev}" ] || [ ! -d "/sys/class/net/${adb_wandev}" ]
469 then
470 rc=145
471 f_log "no valid network device for given logical WAN interface found, please set 'adb_wanif' manually" "${rc}"
472 f_restore
473 fi
474 fi
475 check="$(cat /sys/class/net/${adb_wandev}/operstate 2>/dev/null)"
476 if [ "${check}" = "up" ]
477 then
478 f_log "get active wan update interface/device (${adb_wanif}/${adb_wandev})"
479 break 2
480 elif [ $((adb_cnt)) -eq $((adb_maxloop)) ]
481 then
482 rc=145
483 f_log "wan update interface/device not running (${adb_wanif}/${adb_wandev})" "${rc}"
484 f_restore
485 fi
486 adb_cnt=$((adb_cnt + 1))
487 sleep 1
488 done
489 done
490
491 # ntp time sync
492 #
493 if [ -n "${adb_ntpsrv}" ]
494 then
495 unset ntp_pool
496 for srv in ${adb_ntpsrv}
497 do
498 ntp_pool="${ntp_pool} -p ${srv}"
499 done
500 /usr/sbin/ntpd -nq ${ntp_pool} >/dev/null 2>&1
501 rc=${?}
502 if [ $((rc)) -eq 0 ]
503 then
504 f_log "get ntp time sync"
505 else
506 rc=0
507 f_log "ntp time sync failed"
508 fi
509 fi
510
511 # set dnsmasq defaults
512 #
513 if [ -n "${adb_wanif4}" ] && [ -n "${adb_wanif6}" ]
514 then
515 adb_dnsformat="awk -v ipv4="${adb_nullipv4}" -v ipv6="${adb_nullipv6}" '{print \"address=/\"\$0\"/\"ipv4\"\n\"\"address=/\"\$0\"/\"ipv6}'"
516 elif [ -n "${adb_wanif4}" ]
517 then
518 adb_dnsformat="awk -v ipv4="${adb_nullipv4}" '{print \"address=/\"\$0\"/\"ipv4}'"
519 elif [ -n "${adb_wanif6}" ]
520 then
521 adb_dnsformat="awk -v ipv6="${adb_nullipv6}" '{print \"address=/\"\$0\"/\"ipv6}'"
522 fi
523
524 # remove no longer used opkg package list
525 #
526 unset pkg_list
527 }
528
529 ######################################
530 # f_depend: check package dependencies
531 #
532 f_depend()
533 {
534 local package="${1}"
535
536 check="$(printf "${pkg_list}" | grep "^${package} -" 2>/dev/null)"
537 if [ -z "${check}" ]
538 then
539 rc=150
540 f_log "package '${package}' not found" "${rc}"
541 f_exit
542 fi
543 }
544
545 ##############################################
546 # f_firewall: set iptables rules for ipv4/ipv6
547 #
548 f_firewall()
549 {
550 local ipt
551 local iptv4="/usr/sbin/iptables"
552 local iptv6="/usr/sbin/ip6tables"
553 local proto="${1}"
554 local table="${2}"
555 local ctype="${3}"
556 local chain="${4}"
557 local notes="${5}"
558 local rules="${6}"
559
560 # select appropriate iptables executable
561 #
562 if [ "${proto}" = "IPv4" ]
563 then
564 ipt="${iptv4}"
565 else
566 ipt="${iptv6}"
567 fi
568
569 # check whether iptables rule already applied and proceed accordingly
570 #
571 rc="$("${ipt}" -w -t "${table}" -C "${chain}" -m comment --comment "${notes}" ${rules} >/dev/null 2>&1; printf ${?})"
572 if [ $((rc)) -ne 0 ]
573 then
574 "${ipt}" -w -t "${table}" -"${ctype}" "${chain}" -m comment --comment "${notes}" ${rules} >/dev/null 2>&1
575 rc=${?}
576 if [ $((rc)) -eq 0 ]
577 then
578 fw_done="true"
579 else
580 f_log "failed to initialize volatile ${proto} firewall rule '${notes}'" "${rc}"
581 f_restore
582 fi
583 fi
584 }
585
586 ###################################################
587 # f_log: log messages to stdout, syslog and logfile
588 #
589 f_log()
590 {
591 local log_parm
592 local log_msg="${1}"
593 local log_rc="${2}"
594 local class="info "
595
596 # check for terminal session
597 #
598 if [ -t 1 ]
599 then
600 log_parm="-s"
601 fi
602
603 # log to different output devices, set log class accordingly
604 #
605 if [ -n "${log_msg}" ]
606 then
607 if [ $((log_rc)) -gt 0 ]
608 then
609 class="error"
610 log_rc=", rc: ${log_rc}"
611 log_msg="${log_msg}${log_rc}"
612 fi
613 /usr/bin/logger ${log_parm} -t "adblock[${adb_pid}] ${class}" "${log_msg}"
614 if [ "${log_ok}" = "true" ]
615 then
616 printf "%s\n" "$(/bin/date "+%d.%m.%Y %H:%M:%S") adblock[${adb_pid}] ${class}: ${log_msg}" >> "${adb_logfile}"
617 fi
618 fi
619 }
620
621 ################################################
622 # f_space: check mount points/space requirements
623 #
624 f_space()
625 {
626 local mp="${1}"
627
628 # check relevant mount points in a subshell
629 #
630 if [ -d "${mp}" ]
631 then
632 av_space="$(df "${mp}" 2>/dev/null | tail -n1 2>/dev/null | awk '{print $4}')"
633 if [ $((av_space)) -lt $((adb_minspace)) ]
634 then
635 space_ok="false"
636 fi
637 fi
638 }
639
640 ##################################################################
641 # f_restore: restore last adblock list backups and restart dnsmasq
642 #
643 f_restore()
644 {
645 local rm_done
646 local restore_done
647
648 # remove bogus adblock lists
649 #
650 if [ -n "${adb_revsrclist}" ]
651 then
652 rm_done="$(find "${adb_dnsdir}" -maxdepth 1 -type f \( ${adb_revsrclist} \) -print -exec rm -f "{}" \; 2>/dev/null)"
653 rc=${?}
654 if [ $((rc)) -eq 0 ] && [ -n "${rm_done}" ]
655 then
656 f_log "all bogus adblock lists removed"
657 elif [ $((rc)) -ne 0 ]
658 then
659 f_log "error during removal of bogus adblock lists" "${rc}"
660 f_exit
661 fi
662 fi
663
664 # restore backups
665 #
666 if [ "${backup_ok}" = "true" ] && [ "$(printf "${adb_backupdir}/${adb_dnsprefix}."*)" != "${adb_backupdir}/${adb_dnsprefix}.*" ]
667 then
668 restore_done="$(find "${adb_backupdir}" -maxdepth 1 -type f -name "${adb_dnsprefix}.*" -print -exec cp -pf "{}" "${adb_dnsdir}" \; 2>/dev/null)"
669 rc=${?}
670 if [ $((rc)) -eq 0 ] && [ -n "${restore_done}" ]
671 then
672 f_log "all available backups restored"
673 elif [ $((rc)) -ne 0 ]
674 then
675 f_log "error during restore of adblock lists" "${rc}"
676 f_exit
677 fi
678 else
679 f_log "no backups found, nothing to restore"
680 fi
681
682 # (re-)try dnsmasq restart without bogus adblock lists / with backups
683 #
684 if [ -n "${restore_done}" ] || [ -n "${rm_done}" ]
685 then
686 /etc/init.d/dnsmasq restart >/dev/null 2>&1
687 sleep 2
688 dns_status="$(ps 2>/dev/null | grep "[d]nsmasq" 2>/dev/null)"
689 if [ -n "${dns_status}" ]
690 then
691 rc=0
692 if [ -n "${adb_wanif4}" ] && [ -n "${adb_wanif6}" ]
693 then
694 adb_count="$(($(head -qn -4 "${adb_dnsdir}/${adb_dnsprefix}."* 2>/dev/null | wc -l) / 2))"
695 else
696 adb_count="$(head -qn -4 "${adb_dnsdir}/${adb_dnsprefix}."* 2>/dev/null | wc -l)"
697 fi
698 f_log "adblock lists with overall ${adb_count} domains loaded"
699 else
700 rc=160
701 f_log "dnsmasq restart failed, please check 'logread' output" "${rc}"
702 fi
703 fi
704 f_exit
705 }
706
707 ###################################
708 # f_exit: delete (temporary) files,
709 # generate statistics and exit
710 #
711 f_exit()
712 {
713 local ipv4_prerouting
714 local ipv4_forward
715 local ipv4_output
716 local ipv6_prerouting
717 local ipv6_forward
718 local ipv6_output
719 local iptv4="/usr/sbin/iptables"
720 local iptv6="/usr/sbin/ip6tables"
721
722 # delete temporary files & directories
723 #
724 if [ -f "${adb_tmpfile}" ]
725 then
726 rm -f "${adb_tmpfile}" >/dev/null 2>&1
727 fi
728 if [ -d "${adb_tmpdir}" ]
729 then
730 rm -rf "${adb_tmpdir}" >/dev/null 2>&1
731 fi
732
733 # final log message and iptables statistics
734 #
735 if [ $((rc)) -eq 0 ]
736 then
737 if [ -n "${adb_wanif4}" ]
738 then
739 ipv4_prerouting="$(${iptv4} -t nat -vnL | awk '$11 ~ /^adb-prerouting$/ {sum += $1} END {print sum}')"
740 ipv4_forward="$(${iptv4} -vnL | awk '$11 ~ /^adb-forward$/ {sum += $1} END {print sum}')"
741 ipv4_output="$(${iptv4} -vnL | awk '$11 ~ /^adb-output$/ {sum += $1} END {print sum}')"
742 fi
743 if [ -n "${adb_wanif6}" ]
744 then
745 ipv6_prerouting="$(${iptv6} -t nat -vnL | awk '$11 ~ /^adb-prerouting$/ {sum += $1} END {print sum}')"
746 ipv6_forward="$(${iptv6} -vnL | awk '$11 ~ /^adb-forward$/ {sum += $1} END {print sum}')"
747 ipv6_output="$(${iptv6} -vnL | awk '$11 ~ /^adb-output$/ {sum += $1} END {print sum}')"
748 fi
749 if [ -n "${adb_wanif4}" ] && [ -n "${adb_wanif6}" ]
750 then
751 f_log "adblock firewall statistics (IPv4/IPv6):"
752 f_log "${ipv4_prerouting}/${ipv6_prerouting} packets redirected in PREROUTING chain"
753 f_log "${ipv4_forward}/${ipv6_forward} packets rejected in FORWARD chain"
754 f_log "${ipv4_output}/${ipv6_output} packets rejected in OUTPUT chain"
755 elif [ -n "${adb_wanif4}" ]
756 then
757 f_log "adblock firewall statistics (IPv4):"
758 f_log "${ipv4_prerouting} packets redirected in PREROUTING chain"
759 f_log "${ipv4_forward} packets rejected in FORWARD chain"
760 f_log "${ipv4_output} packets rejected in OUTPUT chain"
761 elif [ -n "${adb_wanif6}" ]
762 then
763 f_log "${ipv6_prerouting} packets redirected in PREROUTING chain"
764 f_log "${ipv6_forward} packets rejected in FORWARD chain"
765 f_log "${ipv6_output} packets rejected in OUTPUT chain"
766 fi
767 f_log "domain adblock processing finished successfully (${adb_scriptver}, ${openwrt_version}, $(/bin/date "+%d.%m.%Y %H:%M:%S"))"
768 elif [ $((rc)) -gt 0 ]
769 then
770 f_log "domain adblock processing failed (${adb_scriptver}, ${openwrt_version}, $(/bin/date "+%d.%m.%Y %H:%M:%S"))"
771 else
772 rc=0
773 fi
774 rm -f "${adb_pidfile}" >/dev/null 2>&1
775 exit ${rc}
776 }