unbound: check if red/iface exists before read it
[ipfire-2.x.git] / src / initscripts / system / unbound
1 #!/bin/sh
2 # Begin $rc_base/init.d/unbound
3
4 # Description : Unbound DNS resolver boot script for IPfire
5 # Author      : Marcel Lorenz <marcel.lorenz@ipfire.org>
6
7 . /etc/sysconfig/rc
8 . ${rc_functions}
9
10 TEST_DOMAIN="ipfire.org"
11
12 # This domain will never validate
13 TEST_DOMAIN_FAIL="dnssec-failed.org"
14
15 INSECURE_ZONES=
16 USE_FORWARDERS=1
17 ENABLE_SAFE_SEARCH=off
18
19 # Cache any local zones for 60 seconds
20 LOCAL_TTL=60
21
22 # EDNS buffer size
23 EDNS_DEFAULT_BUFFER_SIZE=4096
24
25 # Load optional configuration
26 [ -e "/etc/sysconfig/unbound" ] && . /etc/sysconfig/unbound
27
28 ip_address_revptr() {
29         local addr=${1}
30
31         local a1 a2 a3 a4
32         IFS=. read -r a1 a2 a3 a4 <<< ${addr}
33
34         echo "${a4}.${a3}.${a2}.${a1}.in-addr.arpa"
35 }
36
37 read_name_servers() {
38         local i
39         for i in 1 2; do
40                 echo "$(</var/ipfire/red/dns${i})"
41         done 2>/dev/null | xargs echo
42 }
43
44 config_header() {
45         echo "# This file is automatically generated and any changes"
46         echo "# will be overwritten. DO NOT EDIT!"
47         echo
48 }
49
50 update_forwarders() {
51         if [ "${USE_FORWARDERS}" = "1" -a -e "/var/ipfire/red/iface" -a "$(</sys/class/net/$(</var/ipfire/red/iface)/carrier)" = "1" ]; then
52                 local forwarders
53                 local broken_forwarders
54
55                 local ns
56                 for ns in $(read_name_servers); do
57                         test_name_server ${ns} &>/dev/null
58                         case "$?" in
59                                 # Only use DNSSEC-validating or DNSSEC-aware name servers
60                                 0|2)
61                                         forwarders="${forwarders} ${ns}"
62                                         ;;
63                                 *)
64                                         broken_forwarders="${broken_forwarders} ${ns}"
65                                         ;;
66                         esac
67                 done
68
69                 # Determine EDNS buffer size
70                 local new_edns_buffer_size=${EDNS_DEFAULT_BUFFER_SIZE}
71
72                 for ns in ${forwarders}; do
73                         local edns_buffer_size=$(ns_determine_edns_buffer_size ${ns})
74                         if [ -n "${edns_buffer_size}" ]; then
75                                 if [ ${edns_buffer_size} -lt ${new_edns_buffer_size} ]; then
76                                         new_edns_buffer_size=${edns_buffer_size}
77                                 fi
78                         fi
79                 done
80
81                 if [ ${new_edns_buffer_size} -lt ${EDNS_DEFAULT_BUFFER_SIZE} ]; then
82                         boot_mesg "EDNS buffer size reduced to ${new_edns_buffer_size}" ${WARNING}
83                         echo_warning
84
85                         unbound-control -q set_option edns-buffer-size: ${new_edns_buffer_size}
86                 fi
87
88                 # Show warning for any broken upstream name servers
89                 if [ -n "${broken_forwarders}" ]; then
90                         boot_mesg "Ignoring broken upstream name server(s): ${broken_forwarders:1}" ${WARNING}
91                         echo_warning
92                 fi
93
94                 if [ -n "${forwarders}" ]; then
95                         boot_mesg "Configuring upstream name server(s): ${forwarders:1}" ${INFO}
96                         echo_ok
97
98                         # Make sure DNSSEC is activated
99                         enable_dnssec
100
101                         echo "${forwarders}" > /var/ipfire/red/dns
102                         unbound-control -q forward ${forwarders}
103                         return 0
104
105                 # In case we have found no working forwarders
106                 else
107                         # Test if the recursor mode is available
108                         if can_resolve_root +bufsize=${new_edns_buffer_size}; then
109                                 # Make sure DNSSEC is activated
110                                 enable_dnssec
111
112                                 boot_mesg "Falling back to recursor mode" ${WARNING}
113                                 echo_warning
114
115                         # If not, we set DNSSEC in permissive mode and allow using all recursors
116                         elif [ -n "${broken_forwarders}" ]; then
117                                 disable_dnssec
118
119                                 boot_mesg "DNSSEC has been set to permissive mode" ${FAILURE}
120                                 echo_failure
121
122                                 echo "${broken_forwarders}" > /var/ipfire/red/dns
123                                 unbound-control -q forward ${broken_forwarders}
124                                 return 0
125                         fi
126                 fi
127         fi
128
129         # If forwarders cannot be used we run in recursor mode
130         echo "local recursor" > /var/ipfire/red/dns
131         unbound-control -q forward off
132 }
133
134 own_hostname() {
135         local hostname=$(hostname -f)
136         # 1.1.1.1 is reserved for unused green, skip this
137         if [ -n "${GREEN_ADDRESS}" -a "${GREEN_ADDRESS}" != "1.1.1.1" ]; then
138                 unbound-control -q local_data "${hostname} ${LOCAL_TTL} IN A ${GREEN_ADDRESS}"
139         fi
140
141         local address
142         for address in ${GREEN_ADDRESS} ${BLUE_ADDRESS} ${ORANGE_ADDRESS}; do
143                 [ -n "${address}" ] || continue
144                 [ "${address}" = "1.1.1.1" ] && continue
145
146                 address=$(ip_address_revptr ${address})
147                 unbound-control -q local_data "${address} ${LOCAL_TTL} IN PTR ${hostname}"
148         done
149 }
150
151 update_hosts() {
152         local enabled address hostname domainname generateptr
153
154         while IFS="," read -r enabled address hostname domainname generateptr; do
155                 [ "${enabled}" = "on" ] || continue
156
157                 # Build FQDN
158                 local fqdn="${hostname}.${domainname}"
159
160                 unbound-control -q local_data "${fqdn} ${LOCAL_TTL} IN A ${address}"
161
162                 # Skip reverse resolution if the address equals the GREEN address
163                 [ "${address}" = "${GREEN_ADDRESS}" ] && continue
164
165                 # Skip reverse resolution if user requested not to do so
166                 [ "${generateptr}" = "off" ] && continue
167
168                 # Add RDNS
169                 address=$(ip_address_revptr ${address})
170                 unbound-control -q local_data "${address} ${LOCAL_TTL} IN PTR ${fqdn}"
171         done < /var/ipfire/main/hosts
172 }
173
174 write_forward_conf() {
175         (
176                 config_header
177
178                 local insecure_zones="${INSECURE_ZONES}"
179
180                 local enabled zone server servers remark disable_dnssec rest
181                 while IFS="," read -r enabled zone servers remark disable_dnssec rest; do
182                         # Line must be enabled.
183                         [ "${enabled}" = "on" ] || continue
184
185                         # Zones that end with .local are commonly used for internal
186                         # zones and therefore not signed
187                         case "${zone}" in
188                                 *.local)
189                                         insecure_zones="${insecure_zones} ${zone}"
190                                         ;;
191                                 *)
192                                         if [ "${disable_dnssec}" = "on" ]; then
193                                                 insecure_zones="${insecure_zones} ${zone}"
194                                         fi
195                                         ;;
196                         esac
197
198                         # Reverse-lookup zones must be stubs
199                         case "${zone}" in
200                                 *.in-addr.arpa)
201                                         echo "stub-zone:"
202                                         echo "  name: ${zone}"
203                                         for server in ${servers//|/ }; do
204                                                 if [[ ${server} =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
205                                                         echo "  stub-addr: ${server}"
206                                                 else
207                                                         echo "  stub-host: ${server}"
208                                                 fi
209                                         done
210                                         echo
211                                         echo "server:"
212                                         echo "  local-zone: \"${zone}\" transparent"
213                                         echo
214                                         ;;
215                                 *)
216                                         echo "forward-zone:"
217                                         echo "  name: ${zone}"
218                                         for server in ${servers//|/ }; do
219                                                 if [[ ${server} =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
220                                                         echo "  forward-addr: ${server}"
221                                                 else
222                                                         echo "  forward-host: ${server}"
223                                                 fi
224                                         done
225                                         echo
226                                         ;;
227                         esac
228                 done < /var/ipfire/dnsforward/config
229
230                 if [ -n "${insecure_zones}" ]; then
231                         echo "server:"
232
233                         for zone in ${insecure_zones}; do
234                                 echo "  domain-insecure: ${zone}"
235                         done
236                 fi
237         ) > /etc/unbound/forward.conf
238 }
239
240 write_tuning_conf() {
241         # https://www.unbound.net/documentation/howto_optimise.html
242
243         # Determine number of online processors
244         local processors=$(getconf _NPROCESSORS_ONLN)
245
246         # Determine number of slabs
247         local slabs=1
248         while [ ${slabs} -lt ${processors} ]; do
249                 slabs=$(( ${slabs} * 2 ))
250         done
251
252         # Determine amount of system memory
253         local mem=$(get_memory_amount)
254
255         # In the worst case scenario, unbound can use double the
256         # amount of memory allocated to a cache due to malloc overhead
257
258         # Even larger systems with more than 8GB of RAM
259         if [ ${mem} -ge 8192 ]; then
260                 mem=1024
261
262         # Extra large systems with more than 4GB of RAM
263         elif [ ${mem} -ge 4096 ]; then
264                 mem=512
265
266         # Large systems with more than 2GB of RAM
267         elif [ ${mem} -ge 2048 ]; then
268                 mem=256
269
270         # Medium systems with more than 1GB of RAM
271         elif [ ${mem} -ge 1024 ]; then
272                 mem=128
273
274         # Small systems with less than 256MB of RAM
275         elif [ ${mem} -le 256 ]; then
276                 mem=16
277
278         # Everything else
279         else
280                 mem=64
281         fi
282
283         (
284                 config_header
285
286                 # We run one thread per processor
287                 echo "num-threads: ${processors}"
288                 echo "so-reuseport: yes"
289
290                 # Adjust number of slabs
291                 echo "infra-cache-slabs: ${slabs}"
292                 echo "key-cache-slabs: ${slabs}"
293                 echo "msg-cache-slabs: ${slabs}"
294                 echo "rrset-cache-slabs: ${slabs}"
295
296                 # Slice up the cache
297                 echo "rrset-cache-size: $(( ${mem} / 2 ))m"
298                 echo "msg-cache-size: $(( ${mem} / 4 ))m"
299                 echo "key-cache-size: $(( ${mem} / 4 ))m"
300
301                 # Increase parallel queries
302                 echo "outgoing-range: 8192"
303                 echo "num-queries-per-thread: 4096"
304
305                 # Use larger send/receive buffers
306                 echo "so-sndbuf: 4m"
307                 echo "so-rcvbuf: 4m"
308         ) > /etc/unbound/tuning.conf
309 }
310
311 get_memory_amount() {
312         local key val unit
313
314         while read -r key val unit; do
315                 case "${key}" in
316                         MemTotal:*)
317                                 # Convert to MB
318                                 echo "$(( ${val} / 1024 ))"
319                                 break
320                                 ;;
321                 esac
322         done < /proc/meminfo
323 }
324
325 test_name_server() {
326         local ns=${1}
327         local args
328
329         # Return codes:
330         # 0     DNSSEC validating
331         # 1     Error: unreachable, etc.
332         # 2     DNSSEC aware
333         # 3     NOT DNSSEC-aware
334
335         # Exit when the server is not reachable
336         ns_is_online ${ns} || return 1
337
338         # Determine the maximum edns buffer size that works
339         local edns_buffer_size=$(ns_determine_edns_buffer_size ${ns})
340         if [ -n "${edns_buffer_size}" ]; then
341                 args="${args} +bufsize=${edns_buffer_size}"
342         fi
343
344         local errors
345         for rr in DNSKEY DS RRSIG; do
346                 if ! ns_forwards_${rr} ${ns} ${args}; then
347                         errors="${errors} ${rr}"
348                 fi
349         done
350
351         if [ -n "${errors}" ]; then
352                 echo >&2 "Unable to retrieve the following resource records from ${ns}: ${errors:1}"
353                 return 3
354         fi
355
356         if ns_is_validating ${ns} ${args}; then
357                 # Return 0 if validating
358                 return 0
359         else
360                 # Is DNSSEC-aware
361                 return 2
362         fi
363 }
364
365 # Sends an A query to the nameserver w/o DNSSEC
366 ns_is_online() {
367         local ns=${1}
368         shift
369
370         dig @${ns} +nodnssec A ${TEST_DOMAIN} $@ >/dev/null
371 }
372
373 # Resolving ${TEST_DOMAIN_FAIL} will fail if the nameserver is validating
374 ns_is_validating() {
375         local ns=${1}
376         shift
377
378         if ! dig @${ns} A ${TEST_DOMAIN_FAIL} $@ | grep -q SERVFAIL; then
379                 return 1
380         else
381                 # Determine if NS replies with "ad" data flag if DNSSEC enabled
382                 dig @${ns} +dnssec SOA ${TEST_DOMAIN} $@ | awk -F: '/\;\;\ flags\:/ { s=1; if (/\ ad/) s=0; exit s }'
383         fi
384 }
385
386 # Checks if we can retrieve the DNSKEY for this domain.
387 # dig will print the SOA if nothing was found
388 ns_forwards_DNSKEY() {
389         local ns=${1}
390         shift
391
392         dig @${ns} DNSKEY ${TEST_DOMAIN} $@ | grep -qv SOA
393 }
394
395 ns_forwards_DS() {
396         local ns=${1}
397         shift
398
399         dig @${ns} DS ${TEST_DOMAIN} $@ | grep -qv SOA
400 }
401
402 ns_forwards_RRSIG() {
403         local ns=${1}
404         shift
405
406         dig @${ns} +dnssec A ${TEST_DOMAIN} $@ | grep -q RRSIG
407 }
408
409 ns_supports_tcp() {
410         local ns=${1}
411         shift
412
413         dig @${ns} +tcp A ${TEST_DOMAIN} $@ >/dev/null || return 1
414 }
415
416 ns_determine_edns_buffer_size() {
417         local ns=${1}
418         shift
419
420         local b
421         for b in 4096 2048 1500 1480 1464 1400 1280 512; do
422                 if dig @${ns} +dnssec +bufsize=${b} A ${TEST_DOMAIN} $@ >/dev/null; then
423                         echo "${b}"
424                         return 0
425                 fi
426         done
427
428         return 1
429 }
430
431 get_root_nameservers() {
432         while read -r hostname ttl record address; do
433                 # Searching for A records
434                 [ "${record}" = "A" ] || continue
435
436                 echo "${address}"
437         done < /etc/unbound/root.hints
438 }
439
440 can_resolve_root() {
441         local ns
442         for ns in $(get_root_nameservers); do
443                 if dig @${ns} +dnssec SOA . $@ >/dev/null; then
444                         return 0
445                 fi
446         done
447
448         # none of the servers was reachable
449         return 1
450 }
451
452 enable_dnssec() {
453         local status=$(unbound-control get_option val-permissive-mode)
454
455         # Log DNSSEC status
456         echo "on" > /var/ipfire/red/dnssec-status
457
458         # Don't do anything if DNSSEC is already activated
459         [ "${status}" = "no" ] && return 0
460
461         # Activate DNSSEC and flush cache with any stale and unvalidated data
462         unbound-control -q set_option val-permissive-mode: no
463         unbound-control -q flush_zone .
464 }
465
466 disable_dnssec() {
467         # Log DNSSEC status
468         echo "off" > /var/ipfire/red/dnssec-status
469
470         unbound-control -q set_option val-permissive-mode: yes
471 }
472
473 fix_time_if_dns_fail() {
474         # If DNS still not work try to init ntp with
475         # hardcoded ntp.ipfire.org (81.3.27.46)
476         if [ -e "/var/ipfire/red/iface" -a "$(</sys/class/net/$(</var/ipfire/red/iface)/carrier)" = "1" ]; then
477                 host 0.ipfire.pool.ntp.org > /dev/null 2>&1
478                 if [ "${?}" != "0" ]; then
479                         boot_mesg "DNS still not functioning... Trying to sync time with ntp.ipfire.org (81.3.27.46)..."
480                         loadproc /usr/local/bin/settime 81.3.27.46
481                 fi
482         fi
483 }
484
485 resolve() {
486         local hostname="${1}"
487
488         local found=0
489         local ns
490         for ns in $(read_name_servers); do
491                 local answer
492                 for answer in $(dig +short "@${ns}" A "${hostname}"); do
493                         found=1
494
495                         # Filter out non-IP addresses
496                         if [[ ! "${answer}" =~ \.$ ]]; then
497                                 echo "${answer}"
498                         fi
499                 done
500
501                 # End loop when we have got something
502                 [ ${found} -eq 1 ] && break
503         done
504 }
505
506 # Sets up Safe Search for various search engines
507 write_safe_search_conf() {
508         local google_tlds=(
509                 google.ad
510                 google.ae
511                 google.al
512                 google.am
513                 google.as
514                 google.at
515                 google.az
516                 google.ba
517                 google.be
518                 google.bf
519                 google.bg
520                 google.bi
521                 google.bj
522                 google.bs
523                 google.bt
524                 google.by
525                 google.ca
526                 google.cat
527                 google.cd
528                 google.cf
529                 google.cg
530                 google.ch
531                 google.ci
532                 google.cl
533                 google.cm
534                 google.cn
535                 google.co.ao
536                 google.co.bw
537                 google.co.ck
538                 google.co.cr
539                 google.co.id
540                 google.co.il
541                 google.co.in
542                 google.co.jp
543                 google.co.ke
544                 google.co.kr
545                 google.co.ls
546                 google.com
547                 google.co.ma
548                 google.com.af
549                 google.com.ag
550                 google.com.ai
551                 google.com.ar
552                 google.com.au
553                 google.com.bd
554                 google.com.bh
555                 google.com.bn
556                 google.com.bo
557                 google.com.br
558                 google.com.bz
559                 google.com.co
560                 google.com.cu
561                 google.com.cy
562                 google.com.do
563                 google.com.ec
564                 google.com.eg
565                 google.com.et
566                 google.com.fj
567                 google.com.gh
568                 google.com.gi
569                 google.com.gt
570                 google.com.hk
571                 google.com.jm
572                 google.com.kh
573                 google.com.kw
574                 google.com.lb
575                 google.com.ly
576                 google.com.mm
577                 google.com.mt
578                 google.com.mx
579                 google.com.my
580                 google.com.na
581                 google.com.nf
582                 google.com.ng
583                 google.com.ni
584                 google.com.np
585                 google.com.om
586                 google.com.pa
587                 google.com.pe
588                 google.com.pg
589                 google.com.ph
590                 google.com.pk
591                 google.com.pr
592                 google.com.py
593                 google.com.qa
594                 google.com.sa
595                 google.com.sb
596                 google.com.sg
597                 google.com.sl
598                 google.com.sv
599                 google.com.tj
600                 google.com.tr
601                 google.com.tw
602                 google.com.ua
603                 google.com.uy
604                 google.com.vc
605                 google.com.vn
606                 google.co.mz
607                 google.co.nz
608                 google.co.th
609                 google.co.tz
610                 google.co.ug
611                 google.co.uk
612                 google.co.uz
613                 google.co.ve
614                 google.co.vi
615                 google.co.za
616                 google.co.zm
617                 google.co.zw
618                 google.cv
619                 google.cz
620                 google.de
621                 google.dj
622                 google.dk
623                 google.dm
624                 google.dz
625                 google.ee
626                 google.es
627                 google.fi
628                 google.fm
629                 google.fr
630                 google.ga
631                 google.ge
632                 google.gg
633                 google.gl
634                 google.gm
635                 google.gp
636                 google.gr
637                 google.gy
638                 google.hn
639                 google.hr
640                 google.ht
641                 google.hu
642                 google.ie
643                 google.im
644                 google.iq
645                 google.is
646                 google.it
647                 google.je
648                 google.jo
649                 google.kg
650                 google.ki
651                 google.kz
652                 google.la
653                 google.li
654                 google.lk
655                 google.lt
656                 google.lu
657                 google.lv
658                 google.md
659                 google.me
660                 google.mg
661                 google.mk
662                 google.ml
663                 google.mn
664                 google.ms
665                 google.mu
666                 google.mv
667                 google.mw
668                 google.ne
669                 google.nl
670                 google.no
671                 google.nr
672                 google.nu
673                 google.pl
674                 google.pn
675                 google.ps
676                 google.pt
677                 google.ro
678                 google.rs
679                 google.ru
680                 google.rw
681                 google.sc
682                 google.se
683                 google.sh
684                 google.si
685                 google.sk
686                 google.sm
687                 google.sn
688                 google.so
689                 google.sr
690                 google.st
691                 google.td
692                 google.tg
693                 google.tk
694                 google.tl
695                 google.tm
696                 google.tn
697                 google.to
698                 google.tt
699                 google.vg
700                 google.vu
701                 google.ws
702         )
703
704         (
705                 # Nothing to do if safe search is not enabled
706                 if [ "${ENABLE_SAFE_SEARCH}" != "on" ]; then
707                         exit 0
708                 fi
709
710                 # This all belongs into the server: section
711                 echo "server:"
712
713                 # Bing
714                 echo "  local-zone: bing.com transparent"
715                 for address in $(resolve "strict.bing.com"); do
716                         echo "  local-data: \"www.bing.com ${LOCAL_TTL} IN A ${address}\""
717                 done
718
719                 # DuckDuckGo
720                 echo "  local-zone: duckduckgo.com typetransparent"
721                 for address in $(resolve "safe.duckduckgo.com"); do
722                         echo "  local-data: \"duckduckgo.com ${LOCAL_TTL} IN A ${address}\""
723                 done
724
725                 # Google
726                 addresses="$(resolve "forcesafesearch.google.com")"
727                 local domain
728                 for domain in ${google_tlds[@]}; do
729                         echo "  local-zone: ${domain} transparent"
730                         for address in ${addresses}; do
731                                 echo "  local-data: \"www.${domain} ${LOCAL_TTL} IN A ${address}\""
732                         done
733                 done
734
735                 # Yandex
736                 for domain in yandex.com yandex.ru; do
737                         echo "  local-zone: ${domain} typetransparent"
738                         for address in $(resolve "familysearch.${domain}"); do
739                                 echo "  local-data: \"${domain} ${LOCAL_TTL} IN A ${address}\""
740                         done
741                 done
742
743                 # YouTube
744                 echo "  local-zone: youtube.com transparent"
745                 for address in $(resolve "restrictmoderate.youtube.com"); do
746                         echo "  local-data: \"www.youtube.com ${LOCAL_TTL} IN A ${address}\""
747                 done
748         ) > /etc/unbound/safe-search.conf
749 }
750
751 case "$1" in
752         start)
753                 # Print a nicer messagen when unbound is already running
754                 if pidofproc -s unbound; then
755                         statusproc /usr/sbin/unbound
756                         exit 0
757                 fi
758
759                 eval $(/usr/local/bin/readhash /var/ipfire/ethernet/settings)
760
761                 # Update configuration files
762                 write_tuning_conf
763                 write_forward_conf
764                 write_safe_search_conf
765
766                 boot_mesg "Starting Unbound DNS Proxy..."
767                 loadproc /usr/sbin/unbound || exit $?
768
769                 # Make own hostname resolveable
770                 own_hostname
771
772                 # Update any known forwarding name servers
773                 update_forwarders
774
775                 # Update hosts
776                 update_hosts
777
778                 fix_time_if_dns_fail
779                 ;;
780
781         stop)
782                 boot_mesg "Stopping Unbound DNS Proxy..."
783                 killproc /usr/sbin/unbound
784                 ;;
785
786         restart)
787                 $0 stop
788                 sleep 1
789                 $0 start
790                 ;;
791
792         status)
793                 statusproc /usr/sbin/unbound
794                 ;;
795
796         update-forwarders)
797                 # Do not try updating forwarders when unbound is not running
798                 if ! pgrep unbound &>/dev/null; then
799                         exit 0
800                 fi
801
802                 update_forwarders
803
804                 unbound-control flush_negative > /dev/null
805                 unbound-control flush_bogus > /dev/null
806
807                 fix_time_if_dns_fail
808                 ;;
809
810         test-name-server)
811                 ns=${2}
812
813                 test_name_server ${ns}
814                 ret=${?}
815
816                 case "${ret}" in
817                         0)
818                                 echo "${ns} is validating"
819                                 ;;
820                         2)
821                                 echo "${ns} is DNSSEC-aware"
822                                 ;;
823                         3)
824                                 echo "${ns} is NOT DNSSEC-aware"
825                                 ;;
826                         *)
827                                 echo "Test failed for an unknown reason"
828                                 exit ${ret}
829                                 ;;
830                 esac
831
832                 if ns_supports_tcp ${ns}; then
833                         echo "${ns} supports TCP fallback"
834                 else
835                         echo "${ns} does not support TCP fallback"
836                 fi
837
838                 edns_buffer_size=$(ns_determine_edns_buffer_size ${ns})
839                 if [ -n "${edns_buffer_size}" ]; then
840                         echo "EDNS buffer size for ${ns}: ${edns_buffer_size}"
841                 fi
842
843                 exit ${ret}
844                 ;;
845
846         resolve)
847                 resolve "${2}"
848                 ;;
849
850         *)
851                 echo "Usage: $0 {start|stop|restart|status|update-forwarders|test-name-server|resolve}"
852                 exit 1
853                 ;;
854 esac
855
856 # End $rc_base/init.d/unbound