--- /dev/null
+#
+# Copyright (C) 2015-2019 CZ.NIC, z. s. p. o. (https://www.nic.cz/)
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+PKG_RELRO_FULL:=0
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=knot-resolver
+PKG_VERSION:=__VERSION__
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
+
+PKG_MAINTAINER:=Knot DNS <knot-dns@labs.nic.cz>
+PKG_LICENSE:=GPL-3.0
+
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/knot-resolver
+ SECTION:=net
+ CATEGORY:=Network
+ SUBMENU:=IP Addresses and Names
+ TITLE:=Knot DNS Resolver
+ URL:=https://gitlab.labs.nic.cz/knot/resolver
+ DEPENDS=+knot-libs +knot-libzscanner +libuv +luajit +dnssec-rootkey +resolver-conf +luasec +luasocket +libstdcpp
+ PROVIDES:=dns-resolver
+endef
+
+define Package/knot-resolver/description
+ The Knot DNS Resolver is a minimalistic caching resolver implementation.
+endef
+
+MAKE_FLAGS += \
+ PREFIX=/usr \
+ ETCDIR=/etc/kresd
+
+define Build/Patch
+ $(Build/Patch/Default)
+ cd $(PKG_BUILD_DIR) && \
+ sed -i -e 's/\(.*find_lib,hiredis.*\)/HAS_hiredis := no/' \
+ -e 's/\(.*find_lib,libmemcached.*\)/HAS_libmemcached := no/' Makefile
+endef
+
+define Package/knot-resolver/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/*bin/kresd $(1)/usr/bin/
+
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libkres.so* $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/kdns_modules $(1)/usr/lib
+
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/kresd.init $(1)/etc/init.d/kresd
+
+ $(INSTALL_DIR) $(1)/etc/kresd
+ $(CP) $(PKG_BUILD_DIR)/etc/icann-ca.pem $(1)/etc/kresd
+ $(CP) $(PKG_BUILD_DIR)/etc/root.hints $(1)/etc/kresd
+ $(INSTALL_BIN) ./files/kresd.postinst $(1)/etc/kresd/kresd.postinst.sh
+ $(INSTALL_BIN) ./files/convert_config.sh $(1)/etc/kresd/convert_config.sh
+endef
+
+define Package/$(PKG_NAME)/postinst
+#!/bin/sh
+set -x
+if [ -z "$$IPKG_INSTROOT" ]; then
+/etc/init.d/dnsmasq restart
+sleep 2 # Cooldown for above (problems in times of reinstall)
+/etc/kresd/kresd.postinst.sh && rm /etc/kresd/kresd.postinst.sh
+/etc/kresd/convert_config.sh && rm /etc/kresd/convert_config.sh
+if [ "`uci -q get resolver.common.prefered_resolver`" = kresd ] && uci -q get resolver.common.forward_upstream | egrep -q '(1|yes|true|enabled|on)'; then
+ ping -c 1 api.turris.cz 2> /dev/null >&2 || {
+ uci set resolver.common.forward_upstream=0
+ uci commit
+ /etc/init.d/resolver restart
+ if ping -c 1 api.turris.cz 2> /dev/null >&2; then
+ create_notification -s error "DNS servery vašeho poskytovatele internetu nefungují úplně dobře - pravděpodobně nepodporují DNSSEC. Bylo proto vypnuto forwardování a váš router bude nyní vyhodnocovat DNS dotazy sám." "Your ISPs DNS servers does not work properly - most likely they don't support DNSSEC. Therefore DNS forwarding was turned off and your router will now resolve all DNS queries by itself."
+ else
+ uci set resolver.common.forward_upstream=1
+ uci commit
+ /etc/init.d/resolver restart
+ fi
+ }
+fi
+fi
+endef
+
+define Package/$(PKG_NAME)/prerm
+#!/bin/sh
+set -ex
+if [ -z "$$IPKG_INSTROOT" ]; then
+# Remove the script if it is there.
+if [ -e /etc/init.d/kresd ] ; then /etc/init.d/kresd stop ; /etc/init.d/kresd disable ; fi
+fi
+endef
+
+define Package/knot-resolver/postrm
+#!/bin/sh
+if [ -z "$$IPKG_INSTROOT" ]; then
+[ \! -x /etc/init.d/resolver ] || /etc/init.d/resolver restart
+fi
+endef
+
+$(eval $(call BuildPackage,knot-resolver))
+
--- /dev/null
+#!/bin/sh /etc/rc.common
+
+START=61
+STOP=00
+
+USE_PROCD=1
+PROG=/usr/bin/kresd
+CONFIGFILE=/tmp/kresd.config
+ROOTKEYFILE=/etc/root.keys
+DEFAULT_RUNDIR=/tmp/kresd
+STATIC_DOMAINS=1
+DYNAMIC_DOMAINS=0
+USERNAME=kresd
+GROUP=kresd
+
+# Check the /etc/unbound/root.keys is reasonable and try to fix it with given command
+check_root_key() {
+ # Don't do anything if it looks OK
+ grep -qE '[[:space:]](DNSKEY|DS|TYPE[[:digit:]][[:digit:]])[[:space:]]' $ROOTKEYFILE && return
+ # Not OK -> run the command and hope for the best
+ echo "Trying to restore broken $ROOTKEYFILE with command $@"
+ eval "$@"
+}
+
+print() {
+ echo "...---..."
+}
+
+service_triggers() {
+ procd_add_reload_trigger "dhcp"
+}
+
+add_listen_addr() {
+ local addr="$1"
+ local port="$2"
+ [ "$addr" = "::0" ] && addr="::"
+ procd_append_param command -a "$addr#$port"
+}
+
+init_header() {
+ echo "--Automatically generated file; DO NOT EDIT" > $CONFIGFILE
+ echo "modules = {" >> $CONFIGFILE
+ config_get_bool prefetch common prefetch 0
+ echo " 'hints > iterate'" >> $CONFIGFILE
+ echo " , 'policy'" >> $CONFIGFILE
+ if [ "$prefetch" \!= 0 ]; then
+ echo " , 'stats'" >> $CONFIGFILE
+ echo " , predict = {" >> $CONFIGFILE
+ echo " window = 30 -- 30 minutes sampling window" >> $CONFIGFILE
+ echo " , period = 24*(60/30) -- track last 24 hours" >> $CONFIGFILE
+ echo " }" >> $CONFIGFILE
+ fi
+ echo "}" >> $CONFIGFILE
+
+ echo "hints.use_nodata(true)" >> $CONFIGFILE
+
+ # clear hints file
+ echo "" > $HINTS_CONFIG
+}
+
+set_param_func() {
+ local func_name="$1"
+ local val="$2"
+ echo "$func_name($val)">>$CONFIGFILE
+}
+
+set_param_var() {
+ local name="$1"
+ local val="$2"
+ echo "$name=$val">>$CONFIGFILE
+}
+
+include_custom_config() {
+ local custom_config_path
+ config_get custom_config_path "kresd" include_config
+ if [ -e "$custom_config_path" ]; then
+ echo "" >> $CONFIGFILE
+ echo "--- Included custom configuration file from: ---" >> $CONFIGFILE
+ echo "--- $custom_config_path " >> $CONFIGFILE
+ cat $custom_config_path >> $CONFIGFILE
+ else
+ [ -z "$custom_config_path" ] || echo "Warning! Kresd custom config file $custom_config_path doesn't exist."
+ fi
+}
+
+load_uci_config_common() {
+ local interface keyfile verbose port msg_buffer_size net_ipv4 net_ipv6 msg_cache_size do_forward ignore_root_key keep_cache_bool
+ local forward_dns
+ local section="common"
+
+ # port
+ config_get port "$section" port
+
+ # list of listen addresses
+ config_list_foreach "$section" interface add_listen_addr $port
+
+ # ignore keyfile
+ config_get_bool ignore_root_key "$section" ignore_root_key 0
+
+ if [ "$ignore_root_key" = "0" ]; then
+ #keyfile
+ config_get keyfile "$section" keyfile
+ if [ -n "$keyfile" ]; then
+ ROOTKEYFILE=$keyfile
+ check_root_key cert-backup -x $ROOTKEYFILE
+ procd_append_param command -k "$keyfile"
+ fi
+ fi
+
+ # verbosity
+ config_get verbose "$section" verbose 0
+ [ "$verbose" -ge 1 ] && procd_append_param command -v
+
+ # EDNS payload
+ config_get msg_buffer_size "$section" msg_buffer_size
+ [ "$msg_buffer_size" -ge 512 ] && set_param_func "net.bufsize" "$msg_buffer_size"
+
+ # ipv4
+ config_get_bool net_ipv4 "$section" net_ipv4
+ net_ipv4_bool=$(if test "$net_ipv4" -eq "1"; then echo true; else echo false; fi)
+ set_param_var "net.ipv4" "$net_ipv4_bool"
+
+ # ipv6
+ config_get_bool net_ipv6 "$section" net_ipv6
+ net_ipv6_bool=$(if test "$net_ipv6" -eq "1"; then echo true; else echo false; fi)
+ set_param_var "net.ipv6" "$net_ipv6_bool"
+
+ # msg_cache_size
+ config_get msg_cache_size "$section" msg_cache_size
+ conv_msg_cache_size=$(echo "$msg_cache_size"|sed -e 's/k$/*kB/gi' -e 's/M$/*MB/gi' -e 's/G$/*GB/gi')
+ set_param_func "cache.open" "$conv_msg_cache_size"
+
+ # clear cache
+ config_get_bool keep_cache_bool "kresd" keep_cache 1
+ if [ "$keep_cache_bool" = "0" ]; then
+ set_param_func "cache.clear" ""
+ fi
+
+ config_get_bool do_forward "$section" forward_upstream 1
+ config_get forward_dns "$section" forward_custom
+
+ #check custom forwarding
+ if [ -n "$forward_dns" ] && [ "$do_forward" = "1" ]; then
+ dns_config_load "$forward_dns"
+ else
+ if [ "$do_forward" = "1" ] ; then
+ local SERVERS
+ SERVERS=$(sed -ne 's/^nameserver \(.*\)/\1/p' /tmp/resolv.conf.auto | sort -u |head -n 4)
+ if [ "$SERVERS" ] ; then
+ if [ "$ignore_root_key" = "1" ] ; then
+ echo "policy.add(policy.all(policy.STUB({">>$CONFIGFILE
+ else
+ echo "policy.add(policy.all(policy.FORWARD({">>$CONFIGFILE
+ fi
+ for SERVER in $SERVERS ; do
+ echo " '$SERVER',">>$CONFIGFILE
+ done
+ echo "})))">>$CONFIGFILE
+ fi
+ fi
+ md5sum /tmp/resolv.conf.auto | cut -f1 -d\ >/tmp/resolv.conf.auto.last.md5
+ fi
+
+ # enable static local domains
+ config_get_bool STATIC_DOMAINS "$section" static_domains 1
+
+ # get dynamic domains
+ config_get_bool DYNAMIC_DOMAINS "$section" dynamic_domains 1
+
+ # include custom kresd config
+ include_custom_config
+}
+
+get_local_domain() {
+ config_get DOMAIN $1 local
+ [ -z "$DOMAIN" ] || DOMAIN="`echo "$DOMAIN" | sed 's|/||g'`"
+}
+
+set_local_host() {
+ config_get NAME $1 name
+ config_get IP $1 ip
+ if [ -n "$NAME" ] && [ -n "$DOMAIN" ] && [ -n "$IP" ]; then
+ echo "$IP $NAME.$DOMAIN" >> $HINTS_CONFIG
+ fi
+}
+
+get_dnsmasq_dhcp_script() {
+ local config="$1"
+ local DHCPSCRIPT
+ config_get DHCPSCRIPT "$config" dhcpscript
+ echo $DHCPSCRIPT
+}
+
+add_rpz_file() {
+ local rpz_file="$1"
+ if [ -e "$rpz_file" ]; then
+ echo "policy.add(policy.rpz(policy.DENY, '$rpz_file'))" >>$CONFIGFILE
+ fi
+}
+
+add_hostname_config() {
+ local hostname_config="$1"
+ if [ -e "$hostname_config" ] && [ "$STATIC_DOMAINS" = "1" ]; then
+ cat $hostname_config >> $HINTS_CONFIG
+ fi
+}
+
+modify_rundir() {
+ local rundir
+ local section="kresd"
+
+ #rundir
+ config_get rundir "$section" rundir "$DEFAULT_RUNDIR"
+ if [ ! -d "$rundir" ]; then
+ mkdir -p "$rundir"
+ fi
+ chown -R $USERNAME:$GROUP "$rundir" #maybe we should be more restrictive ...
+ DEFAULT_RUNDIR="$rundir"
+ HINTS_CONFIG=$DEFAULT_RUNDIR/hints.tmp
+}
+
+load_uci_config_kresd() {
+ local addr config keyfile forks verbose log_stderr log_stdout hostname_config
+ local section="kresd"
+
+ # knot-resolver config
+ procd_append_param command -c "$CONFIGFILE"
+
+ # number of forks
+ config_get forks "$section" forks 1
+ procd_append_param command -f "$forks"
+
+ # rundir
+ procd_append_param command "$DEFAULT_RUNDIR"
+
+ # procd stdout/err logging
+ config_get_bool log_stderr "$section" log_stderr 1
+ procd_set_param stderr $log_stderr
+ config_get_bool log_stdout "$section" log_stdout 1
+ procd_set_param stdout $log_stdout
+
+ # hostnames for local DNS
+ config_list_foreach "$section" hostname_config add_hostname_config
+
+ #add rpz files
+ config_list_foreach "$section" rpz_file add_rpz_file
+
+ config_load dhcp
+ config_foreach get_local_domain dnsmasq
+
+ if [ "$STATIC_DOMAINS" = "1" ]; then
+ config_foreach set_local_host host
+ config_foreach set_local_host domain
+ fi
+
+ config_load resolver
+
+ # load hints config
+ set_param_func "hints.config" "'$HINTS_CONFIG'"
+}
+
+run_instance() {
+ procd_open_instance
+ procd_set_param file /etc/config/resolver
+ procd_set_param command "$PROG"
+ procd_set_param respawn
+ modify_rundir
+ init_header
+ load_uci_config_kresd
+ load_uci_config_common
+ procd_close_instance
+ ( sleep 60 # Wait for resolver to start working and system to boot up
+ if ! ip -6 r s | grep -q '^default' &&\
+ ping -c 1 api.turris.cz > /dev/null 2>&1 && \
+ ! ping -6 -c 1 api.turris.cz > /dev/null 2>&1; then
+ echo "net.ipv6 = false" | socat - UNIX-CONNECT:$(sleep 5; ls -1 $DEFAULT_RUNDIR/tty/*) > /dev/null 2>&1
+ fi) &
+}
+
+
+print_dns_config() {
+ local name description enable_tls port ipv4 ipv6 pin_sha256 hostname ca_file
+ local net_ipv6 net_ipv4
+
+ name="$1"
+ description="$2"
+ enable_tls="$3"
+ port="$4"
+ ipv4="$5"
+ ipv6="$6"
+ pin_sha256="$7"
+ hostname="$8"
+ ca_file="$9"
+ net_ipv4="$10"
+ net_ipv6="$11"
+
+
+ if [ "$net_ipv4" == "1" ] && [ "$net_ipv6" == "1" ]; then
+ if [ ! -z "$ipv4" ] && [ ! -z "$ipv6" ]; then
+ ip_list="$ipv4 $ipv6"
+ elif [ ! -z "$ipv4" ] && [ -z "$ipv6" ]; then
+ ip_list="$ipv4"
+ elif [ -z "$ipv4" ] && [ ! -z "$ipv6" ]; then
+ ip_list="$ipv6"
+ else
+ echo "Error ipv4 and ipv6 not set !"
+ exit -1
+ fi
+ elif [ "$net_ipv4" != "1" ] && [ "$net_ipv6" == "1" ]; then
+ if [ ! -z "$ipv6" ]; then
+ ip_list="$ipv6"
+ else
+ echo "Error ipv6 not set !"
+ exit -1
+ fi
+ elif [ "$net_ipv4" == "1" ] && [ "$net_ipv6" != "1" ]; then
+ if [ ! -z "$ipv4" ]; then
+ ip_list="$ipv4"
+ else
+ echo "Error ipv4 not set !"
+ exit -1
+ fi
+ else
+ echo "net_ipv4=$net_ipv4 net_ipv6=$net_ipv6"
+ echo "Error cannot choose IP address because of net_ipv4 and net_ipv6 settings!"
+ exit -1
+ fi
+
+ #([ "$enable_tls" == "0" ] || [ -z "$enable_tls" ]) && echo -ne "{" >> $CONFIGFILE
+ if [ "$enable_tls" == "1" ]; then
+ echo "policy.add(policy.all(policy.TLS_FORWARD(">>$CONFIGFILE
+ else
+ echo "policy.add(policy.all(policy.FORWARD(">>$CONFIGFILE
+ fi
+ #TODO add stub !!
+
+ echo -ne "{" >> $CONFIGFILE
+ for ip in $ip_list
+ do
+
+ [ "$enable_tls" == "1" ] && echo -ne "{" >> $CONFIGFILE
+ if [ ! -z "$ip" ]; then
+ #check nonstandard port
+ if [ "$port" == "853" ] || [ -z "$port" ]; then
+ echo "'$ip'" >> $CONFIGFILE
+ else
+ echo "'$ip@$port'" >> $CONFIGFILE
+ fi
+
+ #check of DNS-over-TLS
+ if [ "$enable_tls" == "1" ]; then
+
+ #prefer pin
+ if [ ! -z "$pin_sha256" ];then
+ echo -ne "," >> $CONFIGFILE
+ echo "pin_sha256='$pin_sha256'" >> $CONFIGFILE
+ #else use hostname and certificate from system ca storage
+ elif [ ! -z "$hostname" ]; then
+ echo -ne "," >> $CONFIGFILE
+ echo "hostname='$hostname'" >> $CONFIGFILE
+ #or use ca file if defined
+ if [ ! -z "$ca_file" ] && [ -f "$ca_file" ];then
+ echo -ne "," >> $CONFIGFILE
+ echo "ca_file='$ca_file'" >> $CONFIGFILE
+ fi
+ fi
+ fi
+ fi
+
+ last_item=$(echo $ip_list | awk '{print $NF}')
+ if [ "$enable_tls" == "1" ] && [ "$last_item" != "$ip" ] ; then
+ echo -ne "}," >> $CONFIGFILE
+ elif [ "$enable_tls" == "1" ] && [ "$last_item" == "$ip" ] ; then
+ echo -ne "}" >> $CONFIGFILE
+ elif ([ "$enable_tls" == "0" ] || [ -z "$enable_tls" ]) && [ "$last_item" != "$ip" ]; then
+ echo -ne "," >> $CONFIGFILE
+ fi
+ done
+ echo -ne "}" >> $CONFIGFILE
+ echo ")))" >>$CONFIGFILE
+}
+
+dns_config_load() {
+ local config_name config_file ret
+ local name description enable_tls port ipv4 ipv6 pin_sha256 hostname ca_file
+ local net_ipv4 net_ipv6
+
+ config_name="$1"
+ config_file="/etc/resolver/dns_servers/${config_name}.conf"
+ config_load resolver
+
+ #check file config file
+ if [ -f "$config_file" ]; then
+ enable_tls="0" #set default value
+ config_get net_ipv6 "common" "net_ipv6" 1
+ config_get net_ipv4 "common" "net_ipv4" 1
+
+ echo "loading file from ... $config_file"
+ source $config_file
+ echo print_dns_config "$name" "$description" "$enable_tls" "$port" "$ipv4" "$ipv6" "$pin_sha256" "$hostname" "$ca_file" "$net_ipv4" "$net_ipv6"
+ print_dns_config "$name" "$description" "$enable_tls" "$port" "$ipv4" "$ipv6" "$pin_sha256" "$hostname" "$ca_file" "$net_ipv4" "$net_ipv6"
+ else
+ echo "Error DNS Resolver config not found!"
+ fi
+ echo "ret_value_dns_load=$ret"
+}
+
+
+start_service() {
+ config_load resolver
+ run_instance
+}
+
+reload_service()
+{
+ stop
+ start
+}