Home / Alt manpages / org.freedesktop.resolve1(5)

  • org.freedesktop.resolve1(5)
  • File format
  • linux

Inspect and Configure systemd-resolved over D-Bus

DNS lookups are behaving oddly on one interface and resolvectl alone will not tell you why, so you go to the source. This guide inspects the org.freedesktop.resolve1 service, translates a Linux interface index into a resolver link object, and walks through the per-link calls that actually change DNS behaviour. Allow about twenty minutes.

This targets systemd 255, Ubuntu package build 255.4-1ubuntu8.17. You need gdbus, ip and a running system bus. Read-only inspection needs no elevated privileges. Changing resolver settings can interrupt name lookups and may get overwritten by NetworkManager or systemd-networkd, so pick a maintenance window and keep the previous state on hand before changing anything.

1. Confirm the local API and service

Check the installed systemd version and the resolver helper first. Both are read-only:

$ systemctl --version | head -n 1
systemd 255 (255.4-1ubuntu8.17)
$ command -v gdbus
/usr/bin/gdbus
$ resolvectl status

The last command prints the resolver's current global and per-link state; your servers, interface names and protocol settings will differ. A service that is not running may still leave something else answering through a different resolver path, but D-Bus calls to this name will not work until systemd-resolved.service is up.

Checkpoint: if the status output names a resolver you do not recognise, stop and identify which service actually owns DNS on the host before configuring a second manager on top of it.

2. Discover the Manager interface

The manager has a fixed bus name and object path. Ask the system bus what it exports:

$ gdbus introspect --system \
    --dest org.freedesktop.resolve1 \
    --object-path /org/freedesktop/resolve1

Look for org.freedesktop.resolve1.Manager. It has resolver methods such as ResolveHostname, configuration methods such as SetLinkDNS, and read-only properties including DNS, CurrentDNSServer, Domains, DNSSEC and ResolvConfMode. This introspection output is the contract to compare against the installed manpage when a script needs to support more than one systemd release.

If you see Could not connect or a missing-name error, check the unit without touching it:

$ systemctl status systemd-resolved.service --no-pager

Starting or enabling a service is an administrative change, deliberately outside this inspection workflow. If another network manager owns resolver configuration, fix that ownership question before calling this D-Bus API at all.

D-Bus methods use the numeric Linux interface index, not the friendly name. Find the index without changing any network state:

$ ip -o link show dev enp0s31f6
2: enp0s31f6: <BROADCAST,MULTICAST,UP,LOWER_UP> ...

Replace enp0s31f6 with the interface you actually intend to inspect; the leading number, 2 here, is the index. Ask the Manager for the matching object path:

$ gdbus call --system \
    --dest org.freedesktop.resolve1 \
    --object-path /org/freedesktop/resolve1 \
    --method org.freedesktop.resolve1.Manager.GetLink 2
(objectpath '/org/freedesktop/resolve1/link/_2',)

The path encodes the index, but use the returned value rather than building it yourself: indexes get reused once a device disappears.

Use the returned object path to inspect link-specific methods and properties:

$ gdbus introspect --system \
    --dest org.freedesktop.resolve1 \
    --object-path /org/freedesktop/resolve1/link/_2

Pay attention to DNS, DNSEx, Domains, DefaultRoute, LLMNR, MulticastDNS, DNSOverTLS and DNSSEC. ScopesMask describes protocols currently usable on that interface; the other properties describe configured policy. Those are different questions, so a configured option is no guarantee the interface is currently suitable.

Record the state in your change ticket, or just save the introspection output:

$ gdbus introspect --system \
    --dest org.freedesktop.resolve1 \
    --object-path /org/freedesktop/resolve1/link/_2 \
    > resolve1-link-2-before.txt

That file is ordinary local evidence, not a restoration script. Values supplied by DHCP or another network manager can come straight back once the link reconnects.

5. Understand the configuration calls

The Manager provides one-step calls that take an interface index directly, skipping a separate GetLink round trip.

  • SetLinkDNS takes an array of address records: family plus raw address bytes, so an IPv4 server is four bytes and an IPv6 server is sixteen.
  • SetLinkDNSEx additionally accepts a port and DNS name, which matters for DNS-over-TLS SNI.
  • SetLinkDomains takes domains paired with a boolean: false makes a search domain, true makes a routing-only domain. Search domains can qualify single-label names; routing domains only select where matching queries go.
  • SetLinkDefaultRoute, SetLinkDNSSEC, SetLinkDNSOverTLS, SetLinkLLMNR and SetLinkMulticastDNS change the corresponding per-link policy.

Do not paste a made-up server into a live link. The shape below uses placeholders on purpose, it is not a command to run unchanged:

$ gdbus call --system \
    --dest org.freedesktop.resolve1 \
    --object-path /org/freedesktop/resolve1 \
    --method org.freedesktop.resolve1.Manager.SetLinkDNS \
    <IFINDEX> "[(<AF_INET>, [<IPV4_BYTE_1>, <IPV4_BYTE_2>, <IPV4_BYTE_3>, <IPV4_BYTE_4>])]"

For a real change, get the address family constants and byte values from the API or an established network-management tool, then verify with resolvectl status. A syntax error is safer than a guess, but a syntactically valid address can still leave the host unable to resolve names.

Only continue once you have confirmed this D-Bus API is actually the intended configuration owner. Use an approved DNS address and the exact interface index. This call changes live state and may affect applications immediately:

$ sudo gdbus call --system \
    --dest org.freedesktop.resolve1 \
    --object-path /org/freedesktop/resolve1 \
    --method org.freedesktop.resolve1.Manager.SetLinkDNS \
    <IFINDEX> "[(<AF_INET>, [<IPV4_BYTE_1>, <IPV4_BYTE_2>, <IPV4_BYTE_3>, <IPV4_BYTE_4>])]"
()

Use elevated privileges only if local bus policy actually requires them. Check the result immediately:

$ resolvectl status <INTERFACE>
Link <IFINDEX> (<INTERFACE>)
         DNS Servers: <APPROVED_DNS_SERVER>

Recovery: if the result is wrong, or the network manager reports ownership, stop testing and restore the previous configuration through its normal interface. For settings owned directly by this API, RevertLink resets all per-link settings to defaults, but it is not a general undo for DHCP or network-manager state. Treat it as a deliberate administrative action:

$ sudo gdbus call --system \
    --dest org.freedesktop.resolve1 \
    --object-path /org/freedesktop/resolve1 \
    --method org.freedesktop.resolve1.Manager.RevertLink \
    <IFINDEX>
()

7. Diagnose failures without guessing

  • NoSuchLink means the interface index no longer exists. Re-run ip -o link; do not reuse a stale number.
  • LinkBusy means systemd-networkd already owns the interface and supplied its configuration. Change the owning manager instead.
  • NoNameServers means no suitable DNS server was found; NetworkDown means no suitable connected network was available.

For query methods, tell a DNS answer apart from a local API failure: NoSuchRR is the DNS NODATA case, DnsError.NXDOMAIN means the server reported a negative result, and DnssecFailed means validation rejected the response it got. Resource records arrive from the network and the client must validate them before use. Passing flags as zero is the documented default for resolver calls unless your client has a specific reason to request a protocol or restriction.

Done means

  • Confirmed the installed systemd 255 API and resolver service state.
  • Used the live interface index to obtain the matching D-Bus link path.
  • Inspected Manager and Link properties before changing anything.
  • Identified which settings are search domains, routing domains and default-route policy.
  • Authorised, verified and recovered: any live DNS change was checked with resolvectl and had a recovery path.
  • Told apart a stale link, a competing network manager and a genuine DNS response error.