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