Changeset View
Changeset View
Standalone View
Standalone View
resolvectl.in
- This file was added.
| #!/bin/sh | |||||
| # Copyright (c) 2025 Roy Marples | |||||
| # All rights reserved | |||||
| # resolvectl subscriber for resolvconf | |||||
| # Redistribution and use in source and binary forms, with or without | |||||
| # modification, are permitted provided that the following conditions | |||||
| # are met: | |||||
| # * Redistributions of source code must retain the above copyright | |||||
| # notice, this list of conditions and the following disclaimer. | |||||
| # * Redistributions in binary form must reproduce the above | |||||
| # copyright notice, this list of conditions and the following | |||||
| # disclaimer in the documentation and/or other materials provided | |||||
| # with the distribution. | |||||
| # | |||||
| # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |||||
| # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |||||
| # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |||||
| # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |||||
| # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||||
| # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |||||
| # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |||||
| # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |||||
| # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||||
| # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |||||
| # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||||
| [ -f "@SYSCONFDIR@"/resolvconf.conf ] || exit 0 | |||||
| . "@SYSCONFDIR@/resolvconf.conf" || exit 1 | |||||
| case "${resolvectl:-NO}" in | |||||
| [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) ;; | |||||
| *) exit 0;; | |||||
| esac | |||||
| # If we don't have resolvectl or systemd-resolved isn't running then | |||||
| # we can't do much. | |||||
| # We can't persist our data in /run/systemd/resolve/netif/$ifindex | |||||
| # because systemd-resolved keeps it somehow, ie we can't change it | |||||
| # once we have inserted it | |||||
| if ! [ -d /sys/class/net ] || \ | |||||
| ! type resolvectl >/dev/null 2>&1 || \ | |||||
| ! pidof systemd-resolved >/dev/null | |||||
| then | |||||
| exit 1 | |||||
| fi | |||||
| # resolvectl only accepts resolv.conf setup per physical interface | |||||
| # although resolvconf has always hinted that the named configuration | |||||
| # should be $interface.$protocol, this has never been a fixed requirement. | |||||
| # Because resolvectl only accepts one configuration per interface we need | |||||
| # to try and merge the resolv.conf's together. | |||||
| # Luckily resolvconf makes this easy for us. | |||||
| # Returns a list of resolvconf entries for a real interface | |||||
| get_resolvconf_interfaces() { | |||||
| IFACE="$1" | |||||
| [ -d /sys/class/net/"$IFACE" ] || return 1 | |||||
| IFACES= | |||||
| for IFACE_PROTO in $(@SBINDIR@/resolvconf -Li "$IFACE" "$IFACE.*" 2>/dev/null); do | |||||
| # ens5 will work with ens5.dhcp and ens5.ra, | |||||
| # but not ens5.5 or ens5.5.dhcp | |||||
| if [ "$IFACE_PROTO" != "$IFACE" ]; then | |||||
| # Ensure that ens5.5.dhcp doesn't work for ens5 | |||||
| if [ "${IFACE_PROTO%.*}" != "$IFACE" ]; then | |||||
| continue | |||||
| fi | |||||
| # Ensure that ens5.dhcp isn't a real interface | |||||
| # as ens5.5 likely is and the .5 matches the .dhcp | |||||
| if [ -d /sys/class/net/"$IFACE_PROTO" ]; then | |||||
| continue | |||||
| fi | |||||
| fi | |||||
| IFACES="$IFACES${IFACES:+ }$IFACE_PROTO" | |||||
| done | |||||
| echo "$IFACES" | |||||
| } | |||||
| # For the given interface, apply a list of resolvconf entries | |||||
| apply_resolvconf() { | |||||
| IFACE="$1" | |||||
| shift | |||||
| if [ -z "$1" ]; then | |||||
| resolvectl revert "$IFACE" | |||||
| return | |||||
| fi | |||||
| # Set the default-route property first to avoid leakage. | |||||
| # If any entry is private, the whole interface has to be private. | |||||
| # If a more granular approach is needed, consider using the | |||||
| # systemd-resolved subscriber instead which supports DNS delegates. | |||||
| if [ -n "$(@SBINDIR@/resolvconf -p $@)" ]; then | |||||
| resolvectl default-route "$IFACE" false | |||||
| else | |||||
| resolvectl default-route "$IFACE" true | |||||
| fi | |||||
| # Now set domain and dns | |||||
| DOMAIN=$(@SBINDIR@/resolvconf -L $@ 2>/dev/null | sed -n -e "s/domain //p" -e "s/search //p") | |||||
| NS=$(@SBINDIR@/resolvconf -L $@ 2>/dev/null | sed -n -e "s/nameserver //p") | |||||
| if [ -n "$DOMAIN" ]; then | |||||
| # If any entry is marked as not searchable, we mark all the | |||||
| # domains as non searchable. | |||||
| # If a more granular approach is needed, consider using the | |||||
| # systemd-resolved subscriber instead which supports DNS delegates. | |||||
| if [ -n "$(@SBINDIR@/resolvconf -pp $@)" ]; then | |||||
| ND= | |||||
| for d in $DOMAIN; do | |||||
| ND="$ND${ND:+ }~$d" | |||||
| done | |||||
| DOMAIN="$ND" | |||||
| fi | |||||
| resolvectl domain "$IFACE" $DOMAIN | |||||
| else | |||||
| resolvectl domain "$IFACE" "" | |||||
| fi | |||||
| if [ -n "$NS" ]; then | |||||
| resolvectl dns "$IFACE" $NS | |||||
| else | |||||
| resolvectl dns "$IFACE" "" | |||||
| fi | |||||
| } | |||||
| # To get the full features of resolvconf, we need to work out each interface | |||||
| # for every resolvconf addition and deletion | |||||
| # This is because resolvconf.conf might have changed OR an exclusive | |||||
| # interface deleted which makes other interfaces visible. | |||||
| cd /sys/class/net | |||||
| for IFACE in *; do | |||||
| if [ "$IFACE" = lo ]; then | |||||
| # systemd-resolved doesn't work with lo | |||||
| continue | |||||
| fi | |||||
| IFACES=$(get_resolvconf_interfaces "$IFACE") | |||||
| apply_resolvconf "$IFACE" $IFACES | |||||
| done | |||||
| # warn about resolv.conf with no matching interface | |||||
| FAILED= | |||||
| for IFACE_PROTO in $(@SBINDIR@/resolvconf -Li); do | |||||
| IFACE="${IFACE_PROTO%.*}" | |||||
| if [ "$IFACE" = lo ]; then | |||||
| # Don't warn about loopback interface as that is typically | |||||
| # used to configure libc for a nameserver on it and the libc | |||||
| # subscriber will process that just fine. | |||||
| continue | |||||
| fi | |||||
| if ! [ -d "/sys/class/net/$IFACE" ]; then | |||||
| FAILED="$FAILED${FAILED:+ }$IFACE_PROTO" | |||||
| fi | |||||
| done | |||||
| if [ -n "$FAILED" ]; then | |||||
| echo "Could not apply resolv.conf to resolvectl: $FAILED" >&2 | |||||
| fi | |||||