summaryrefslogtreecommitdiff
path: root/assets/2026-01-29-mdns-resolution-fix.org
blob: 54b4983adff81f4f896e01e955a3420f1032c40c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#+TITLE: mDNS Resolution Issue and Fix
#+DATE: 2026-01-29

* Problem

Local network devices advertising via mDNS (multicast DNS) cannot be resolved by hostname. Specifically, =.local= domain names fail to resolve.

** Symptom

When attempting to connect to a network printer by its mDNS hostname:

#+begin_example
$ lpadmin -p "Brother-MFC-J6945DW" -E -v "ipp://Brother%20MFC-J6945DW._ipp._tcp.local/" -m everywhere
lpadmin: Unable to connect to BRW7440BBC7D1BE.local:631: Temporary failure in name resolution
#+end_example

The device is discoverable via Avahi:

#+begin_src bash
avahi-browse -t _ipp._tcp
#+end_src

But the hostname (e.g., =BRW7440BBC7D1BE.local=) cannot be resolved to an IP address by applications.

** Root Cause

Two issues combine to prevent mDNS resolution:

1. The =nss-mdns= package is installed but not configured in =/etc/nsswitch.conf=
2. =systemd-resolved= (the =resolve= entry) intercepts =.local= queries before =mdns_minimal= can handle them

This means:
- =avahi-daemon= is running and can discover mDNS services
- =avahi-browse= and =avahi-resolve= work correctly
- But standard glibc name resolution never queries Avahi because =resolve= handles (and fails) the =.local= lookup first

** Original Configuration

#+begin_example
hosts: mymachines resolve [!UNAVAIL=return] files myhostname dns
#+end_example

The =mdns_minimal= NSS module is missing, and =resolve= (systemd-resolved) comes too early in the chain.

* Solution

Add =mdns_minimal [NOTFOUND=return]= to the hosts line in =/etc/nsswitch.conf=, positioned *before* the =resolve= entry.

** Corrected Configuration

#+begin_example
hosts: mymachines files mdns_minimal [NOTFOUND=return] resolve [!UNAVAIL=return] myhostname dns
#+end_example

** Explanation of the Fix

- =mdns_minimal= - Resolves =.local= hostnames via Avahi/mDNS (minimal version only handles =.local=)
- =[NOTFOUND=return]= - If a =.local= name is not found via mDNS, don't fall through to other resolvers (prevents delays)
- *Order matters:* =mdns_minimal= must come *before* =resolve= (systemd-resolved) because =resolve= will attempt to handle =.local= queries and fail, stopping the resolution chain
- =files= is moved before =mdns_minimal= so =/etc/hosts= entries are checked first

** Why Order Matters

NSS processes entries left-to-right. With the original order:

1. =resolve= receives the =.local= query
2. systemd-resolved has mDNS disabled (=-mDNS= in =resolvectl status=)
3. It returns NOTFOUND, and =[!UNAVAIL=return]= allows fallthrough
4. But =mdns_minimal= was never in the chain to receive the query

With the corrected order:

1. =files= checks =/etc/hosts= first
2. =mdns_minimal= handles =.local= queries via Avahi
3. =[NOTFOUND=return]= prevents =.local= queries from going further if not found
4. =resolve= handles other queries normally

** How to Apply

#+begin_src bash
# Transform the hosts line to insert mdns_minimal before resolve
sudo sed -i 's/mymachines resolve/mymachines files mdns_minimal [NOTFOUND=return] resolve/' /etc/nsswitch.conf
sudo sed -i 's/files files/files/' /etc/nsswitch.conf  # Remove duplicate 'files' if present
#+end_src

Or manually edit =/etc/nsswitch.conf= to match the corrected configuration above.

** Verification

After applying the fix:

#+begin_src bash
# Should resolve the .local hostname to an IP
getent hosts BRW7440BBC7D1BE.local

# Or ping the device by hostname
ping -c 1 BRW7440BBC7D1BE.local
#+end_src

* Workaround (If Fix Cannot Be Applied)

If the fix cannot be applied immediately, use the device's IP address directly instead of the mDNS hostname:

#+begin_src bash
# Find the IP via avahi
avahi-browse -rpkt _ipp._tcp | grep "MFC-J6945"
# Output shows: 192.168.86.37

# Use IP instead of hostname
sudo lpadmin -p "Brother-MFC-J6945DW" -E -v "ipp://192.168.86.37/ipp/print" -m everywhere
#+end_src

* Status

Applied to this system on 2026-01-29. Verified working with Brother MFC-J6945DW printer setup using mDNS hostname.

* References

- Arch Wiki: Avahi - https://wiki.archlinux.org/title/Avahi
- nss-mdns documentation - https://github.com/avahi/nss-mdns