prusa3d / PrusaSlicer

G-code generator for 3D printers (RepRap, Makerbot, Ultimaker etc.)
https://www.prusa3d.com/prusaslicer/
GNU Affero General Public License v3.0
7.69k stars 1.93k forks source link

System resolved bypassed - mDNS/avahi does not work on Linux #11226

Open fff7d1bc opened 1 year ago

fff7d1bc commented 1 year ago

Description of the bug

I am running Linux and have the avahi/mdns configured system wide using /etc/nsswitch.conf

% grep '^hosts:' /etc/nsswitch.conf 
hosts:       files mdns_minimal [NOTFOUND=return] dns mdns

The resolver works as long as it uses system resolver, that is, anything that will run gethostbyname() of libc will work. However when I use PrusaSlicer and add my physical printer with hostname voron-v0.local then it cannot resolve it

Could not connect to Moonraker: Couldn't resolve host name:
Could not resolve host: voron-v0.local
[Error 6]

I did run the slicer though strace and what I seen is that the PrusaSlicer, instead of using system resolver, it directly queries the DNS server, which in my case are Google DNS, so clearly they cannot resolve voron-v0.local address.

[pid  3039] connect(23, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("8.8.8.8")}, 16) = 0 
[pid  3039] sendto(23, "\321\350\1\0\0\1\0\0\0\0\0\0\10voron-v0\5local\0\0\1\0\1", 32, MSG_NOSIGNAL, NULL, 0) = 32 
[pid  3039] getrandom("\xd9\x13", 2, 0) = 2 
[pid  3039] sendto(23, "a\254\1\0\0\1\0\0\0\0\0\0\10voron-v0\5local\0\0\34\0\1", 32, MSG_NOSIGNAL, NULL, 0) = 32 
[pid  3039] poll([{fd=23, events=POLLIN|POLLRDNORM}], 1, 0) = 0 (Timeout) 
[pid  3039] rt_sigaction(SIGPIPE, {sa_handler=SIG_IGN, sa_mask=[PIPE], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0x7f18c6e39d70}, NULL, 8) = 0 
[pid  3039] poll([{fd=23, events=POLLIN}, {fd=21, events=POLLIN}], 2, 1000) = 1 ([{fd=23, revents=POLLIN}]) 
[pid  3039] rt_sigaction(SIGPIPE, NULL, {sa_handler=SIG_IGN, sa_mask=[PIPE], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0x7f18c6e39d70}, 8) = 0 
[pid  3039] rt_sigaction(SIGPIPE, {sa_handler=SIG_IGN, sa_mask=[PIPE], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0x7f18c6e39d70}, NULL, 8) = 0 
[pid  3039] poll([{fd=23, events=POLLIN|POLLRDNORM}], 1, 0) = 1 ([{fd=23, revents=POLLIN|POLLRDNORM}]) 
[pid  3039] recvfrom(23, "\321\350\201\203\0\1\0\0\0\1\0\0\10voron-v0\5local\0\0\1\0\1\0\0\6\0\1\0\1Ql\0@\1a\froot-servers\3net\0\5nstld\fverisign-grs\3com\0x\225\350\30\0\0\7\10\0\0\3\204\0\t:\200\0\1Q\200", 4097, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("8.8.8.8")}, [16]) = 107 
[pid  3039] recvfrom(23, "a\254\201\203\0\1\0\0\0\1\0\0\10voron-v0\5local\0\0\34\0\1\0\0\6\0\1\0\1Qz\0@\1a\froot-servers\3net\0\5nstld\fverisign-grs\3com\0x\225\350\30\0\0\7\10\0\0\3\204\0\t:\200\0\1Q\200", 4097, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("8.8.8.8")}, [16]) = 107 
[pid  3039] close(23)                   = 0 
[pid  3039] rt_sigaction(SIGPIPE, {sa_handler=SIG_IGN, sa_mask=[PIPE], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0x7f18c6e39d70}, NULL, 8) = 0 
[pid  3039] rt_sigaction(SIGPIPE, {sa_handler=SIG_IGN, sa_mask=[PIPE], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0x7f18c6e39d70}, NULL, 8) = 0 
[pid  3039] write(1, "[2023-09-02 10:35:23.271243] [0x00007f18c2ed8dc0] [error]   Moonraker: Error getting version: Couldn't resolve host name:\nCould not resolve host: voron-v0.local\n[Error 6], HTTP 0, body: ``\n", 189[2023-09-02 10:35:23.271243] [0x00007f18c2ed8dc0] [error]   Moonraker: Error getting version: Couldn't resolve host name: 
Could not resolve host: voron-v0.local 
[Error 6], HTTP 0, body: `` 
) = 189 

I suspect this is not an accident that it works this way and most likely was made to not try to use system resolver as the default distribution of PrusaSlicer is statically linked so you cannot really rely on the libc you find there.

In my case this is PrusaSlicer 2.6.0 built natively on Gentoo Linux running glibc.

Potentially the way to solve it without adding you too much other problems would be to create fallback mechanism, that if standard name resolution fails you could instead fallback to call getent hosts HOSTNAME.local and read it's stdout. It is there on both musl libc and glibc and is the standard, though that would mean that you can no longer to just rely on the mechanism that will transparently for you resolve the dns and connect there but you'd need to control it, resolve host to IP and only then make connection to IP, on the top of that, every time you connect there, so every time a button test is clicked or when one sends gcode to printer.

Project file & How to reproduce

1, Have Linux

  1. Have avahi configured in nssswitch.conf
  2. Try to add/test physical printer with the HOSTNAME.local domain
  3. Big sad

Checklist of files included above

Version of PrusaSlicer

2.6.0

Operating system

Gentoo ~amd64 glibc

Printer model

Voron v0.2

nachtsnochlicht commented 10 months ago

Same Problem here with Prusa 2.7 on Fedora 38 with Kernel 6.5.12 !

Prusa is the only application, that can't resolve my printers hostname.

I feel like resolving a local hostname is more valuable to generic users, than resolving via DNS. Who has a printer resolved by a DNS? Most users probably just wan't to use the local hostname and don't worry about local IPs in their home network.

eduncan911 commented 7 months ago

I've seen applications generally developed to allow for mDNS querying by flat-out filtering "*.local" suffix from any type of standard DNS query. And instead, query mDNS resolver.

There are security precautions here to take account: leaking DNS lookups of local devices and services to your ISP, and all... This is why we take ".local" and just query a resolver for it, skipping the dns lookup. Anything else but ".local" goes through the normal flow.


(this is why it is impossible to switch from .local and have it work in all apps, mobiles, etc - just let it go, leave it .local)