From 6c1cf68bca7376c6291c3cfe710ebd5bd5ed3e6c Mon Sep 17 00:00:00 2001 From: ed Date: Sun, 1 Dec 2024 19:01:40 +0000 Subject: [PATCH] mdns: add workaround for https://github.com/avahi/avahi/issues/379 Avahi's mDNS-reflection feature does not understand NSEC, so it corrupts mDNS packets by not rewriting compressed labels --- copyparty/__main__.py | 1 + copyparty/mdns.py | 4 ++++ copyparty/stolen/dnslib/dns.py | 4 ++-- copyparty/stolen/dnslib/label.py | 22 +++++++++++++++++++++- 4 files changed, 28 insertions(+), 3 deletions(-) diff --git a/copyparty/__main__.py b/copyparty/__main__.py index 6cf0ddfe..9696530e 100644 --- a/copyparty/__main__.py +++ b/copyparty/__main__.py @@ -1125,6 +1125,7 @@ def add_zc_mdns(ap): ap2.add_argument("--zmv", action="store_true", help="verbose mdns") ap2.add_argument("--zmvv", action="store_true", help="verboser mdns") ap2.add_argument("--zm-no-pe", action="store_true", help="mute parser errors (invalid incoming MDNS packets)") + ap2.add_argument("--zm-nwa-1", action="store_true", help="disable workaround for avahi-bug #379 (corruption in Avahi's mDNS reflection feature)") ap2.add_argument("--zms", metavar="dhf", type=u, default="", help="list of services to announce -- d=webdav h=http f=ftp s=smb -- lowercase=plaintext uppercase=TLS -- default: all enabled services except http/https (\033[32mDdfs\033[0m if \033[33m--ftp\033[0m and \033[33m--smb\033[0m is set, \033[32mDd\033[0m otherwise)") ap2.add_argument("--zm-ld", metavar="PATH", type=u, default="", help="link a specific folder for webdav shares") ap2.add_argument("--zm-lh", metavar="PATH", type=u, default="", help="link a specific folder for http shares") diff --git a/copyparty/mdns.py b/copyparty/mdns.py index 6329556c..a9d36fe7 100644 --- a/copyparty/mdns.py +++ b/copyparty/mdns.py @@ -25,6 +25,7 @@ from .stolen.dnslib import ( DNSHeader, DNSQuestion, DNSRecord, + set_avahi_379, ) from .util import CachedSet, Daemon, Netdev, list_ips, min_ex @@ -72,6 +73,9 @@ class MDNS(MCast): self.ngen = ngen self.ttl = 300 + if not self.args.zm_nwa_1: + set_avahi_379() + zs = self.args.name + ".local." zs = zs.encode("ascii", "replace").decode("ascii", "replace") self.hn = "-".join(x for x in zs.split("?") if x) or ( diff --git a/copyparty/stolen/dnslib/dns.py b/copyparty/stolen/dnslib/dns.py index 74f26ad7..deba28f2 100644 --- a/copyparty/stolen/dnslib/dns.py +++ b/copyparty/stolen/dnslib/dns.py @@ -8,7 +8,7 @@ from itertools import chain from .bimap import Bimap, BimapError from .bit import get_bits, set_bits from .buffer import BufferError -from .label import DNSBuffer, DNSLabel +from .label import DNSBuffer, DNSLabel, set_avahi_379 from .ranges import IP4, IP6, H, I, check_bytes @@ -426,7 +426,7 @@ class RR(object): if rdlength: rdata = RDMAP.get(QTYPE.get(rtype), RD).parse(buffer, rdlength) else: - rdata = "" + rdata = RD(b"a") return cls(rname, rtype, rclass, ttl, rdata) except (BufferError, BimapError) as e: raise DNSError("Error unpacking RR [offset=%d]: %s" % (buffer.offset, e)) diff --git a/copyparty/stolen/dnslib/label.py b/copyparty/stolen/dnslib/label.py index 20ff3306..22f5da12 100644 --- a/copyparty/stolen/dnslib/label.py +++ b/copyparty/stolen/dnslib/label.py @@ -11,6 +11,25 @@ LDH = set(range(33, 127)) ESCAPE = re.compile(r"\\([0-9][0-9][0-9])") +avahi_379 = 0 + + +def set_avahi_379(): + global avahi_379 + avahi_379 = 1 + + +def log_avahi_379(args): + global avahi_379 + n = avahi_379 + if n == 2: + return + if n == 1: + avahi_379 = 2 + t = "Invalid pointer in DNSLabel [offset=%d,pointer=%d,length=%d]; this is probably avahi-bug #379, packet corruption in Avahi's mDNS reflection feature. Copyparty has a workaround and is OK, but other devices need either --zm4 or --zm6" + raise BufferError(t % args) + + class DNSLabelError(Exception): pass @@ -96,8 +115,9 @@ class DNSBuffer(Buffer): ) if pointer < self.offset: self.offset = pointer + elif avahi_379: + log_avahi_379((self.offset, pointer, len(self.data))) else: - raise BufferError( "Invalid pointer in DNSLabel [offset=%d,pointer=%d,length=%d]" % (self.offset, pointer, len(self.data))