#!/bin/sh -e

UNBOUND_CONF="/etc/unbound/unbound.conf"
UNBOUND_BASE_DIR="${UNBOUND_CONF%/*}"
CHROOT_DIR="$(unbound-checkconf -o chroot)"

DNS_ROOT_KEY_FILE="/usr/share/dns/root.key"
ROOT_TRUST_ANCHOR_FILE="/var/lib/unbound/root.key"

# Override these variables by editing or creating /etc/default/unbound.
RESOLVCONF=true
ROOT_TRUST_ANCHOR_UPDATE=true

if [ -f /etc/default/unbound ]; then
    . /etc/default/unbound

    case "$RESOLVCONF" in false|0|no)
        RESOLVCONF=false ;;
    esac

    case "$ROOT_TRUST_ANCHOR_UPDATE" in false|0|no)
        ROOT_TRUST_ANCHOR_UPDATE=false ;;
    esac
fi

do_resolvconf_start() {
    if $RESOLVCONF; then
        if [ -x /sbin/resolvconf ]; then
            unbound-checkconf $CHROOT_DIR/$UNBOUND_CONF -o interface | (
                default=yes
                while read interface; do
                    default=no
                    if [ "x$interface" = x0.0.0.0 -o "x$interface" = x127.0.0.1 ]; then
                        echo "nameserver 127.0.0.1"
                    elif [ "x$interface" = x::0 -o "x$interface" = x::1 ]; then
                        echo "nameserver ::1"
                    fi
                done
                if [ $default = yes ]; then
                    # unbound defaults to listening on localhost
                    echo "nameserver 127.0.0.1"
                fi
            ) | /sbin/resolvconf -a lo.unbound
        fi
    fi
}

do_resolvconf_stop() {
    if $RESOLVCONF; then
        if [ -x /sbin/resolvconf ]; then
            /sbin/resolvconf -d lo.unbound
        fi
    fi
}

do_chroot_setup() {
    [ -n "$CHROOT_DIR" -a -d "$CHROOT_DIR" ] || return
    if [ "$CHROOT_DIR" != "$UNBOUND_BASE_DIR" ]; then
        # we probably should not do the force-recreate but just a refresh
        rm -rf   "$CHROOT_DIR/$UNBOUND_BASE_DIR"
        mkdir -p "$CHROOT_DIR/$UNBOUND_BASE_DIR"
        tar -C "$UNBOUND_BASE_DIR" -c . |
            tar -C "$CHROOT_DIR/$UNBOUND_BASE_DIR" -x
    fi
    if [ -S "/run/systemd/notify" ]; then
        if [ ! -e "$CHROOT_DIR/run/systemd/notify" ]; then
            mkdir -p "$CHROOT_DIR/run/systemd"
            touch "$CHROOT_DIR/run/systemd/notify"
        fi
        if ! mountpoint -q "$CHROOT_DIR/run/systemd/notify"; then
            mount --bind "/run/systemd/notify" "$CHROOT_DIR/run/systemd/notify"
        fi
    fi
}

do_chroot_teardown() {
    if [ -n "$CHROOT_DIR" -a -d "$CHROOT_DIR" ] &&
       mountpoint -q "$CHROOT_DIR/run/systemd/notify"; then
        umount "$CHROOT_DIR/run/systemd/notify"
    fi
}

do_root_trust_anchor_update() {
    [ false != "$ROOT_TRUST_ANCHOR_UPDATE" -a \
      -n "$ROOT_TRUST_ANCHOR_FILE"  -a \
      -r "$DNS_ROOT_KEY_FILE" ] || return

    if [ ! -e "$ROOT_TRUST_ANCHOR_FILE" ] ||
       # we do not want to copy if unbound's file is more recent
       [ "$DNS_ROOT_KEY_FILE" -nt "$ROOT_TRUST_ANCHOR_FILE" ]; then

        echo "Updating $ROOT_TRUST_ANCHOR_FILE from $DNS_ROOT_KEY_FILE"
        # Copy to temp first and do mv only when done to ensure the file is in
        # good condition.  Can use install(1) here to set correct owner but need
        # mv anyway, and doing both as root in an untrusted dir seems risky.
        setpriv --reuid=unbound --regid=unbound --clear-groups \
          sh -c "\
            cp --remove-destination --preserve \
                 \"$DNS_ROOT_KEY_FILE\" \"$ROOT_TRUST_ANCHOR_FILE.tmp\" && \
            mv -f \"$ROOT_TRUST_ANCHOR_FILE.tmp\" \"$ROOT_TRUST_ANCHOR_FILE\""
    fi
}

case "$1" in
    ( resolvconf_start \
    | resolvconf_stop \
    | chroot_setup \
    | chroot_teardown \
    | root_trust_anchor_update \
    )
        do_$1
        ;;

    (*)
        echo "Usage: $0 {resolvconf_start|resolvconf_stop|chroot_setup|chroot_teardown|root_trust_anchor_update}" >&2
        exit 1
        ;;
esac
