Hi Folkert, > On 8 Dec 2021, at 4:56 am, folkert <[email protected]> wrote: > >> I made a program which sends an mDNS announcement every 121 seconds. >> The TTL is 120 seconds. >> >> Yet every time avahi (with --debug) complains about: >> >> dec 07 10:27:54 lappiemctopface avahi-daemon[937]: Received conflicting >> record [_apple-midi._udp.local IN PTR >> mymdnstest._apple-midi._udp.local ; ttl=120]. Resetting our record. >> >> I've uploaded a pcap: >> https://vps001.vanheusden.com/~folkert/mdns.pcap >> (text dump: https://vps001.vanheusden.com/~folkert/mdns.txt ) >> >> Anyone an idea what is going wrong? > > I just verified that I get this error already on the first packet. > > So I start avahi-daemon, let the other program send the mdns message > once and immediately avahi complains about a conflicting record.
What is sending these other packets? I think there are two main problems. The first one leading to the immediate conflict is that mDNS records can be either “Unique” (owned by a single host) or “Shared” (a record publish by multiple hosts, or, a list of records published in aggregate by multiple hosts). If you refer to RFC6762 Section 10.2 (https://datatracker.ietf.org/doc/html/rfc6762#section-10.2) The semantics of the cache-flush bit are as follows: normally when a resource record appears in a Resource Record Section of the DNS response it means, "This is an assertion that this information is true". When a resource record appears in a Resource Record Section of the DNS response with the cache-flush bit set, it means, "This is an assertion that this information is the truth and the whole truth, and anything you may have heard more than a second ago regarding records of this name/rrtype/rrclass is no longer true”. Unique records such as your hostname ‘mydnstest.local’ are expected to have the cache-flush bit to be set. But for shared resources such as the list of services (_apple-midi._udp.local PTR) we expect a “Shared” record so the cache-flush bit is false. This is because the “_apple-midi._udp.local” record is a shared list of services where multiple services all contribute to the list. Additionally the SRV record looks wrong.. from your text output it says: _apple-midi._udp.local: type SRV, class IN, cache flush, priority 0, weight 0, port 5004, target mymdnstest.local The name of this record should be ‘mydnstest._apple-midi._udp.local’ instead, the same name as the target for the PTR record. The hierarchy of announcements is: (1) PTR from the shared service name (_http._tcp) with a target of your unique service instance (test._http._tcp.local) _http._tcp.local PTR test._http._tcp.local (Shared record, cache-flush=false) (2) SRV record from your unique service name with the port number and target hostname test._http._tcp.local SRV port 80 target primary.local (Non-shared record, cache-flush=true) There may also be a TXT record of the same name with any properties (3) A/AAAA record for the IP address of the target hostname referenced in the SRV (the hostname is usually shared by all services from the same host) primary.local A 192.168.1.1 (Typically non-shared with cache-flush=true) Here is an example Wireshark capture I took just now of publishing a service using avahi (avahi-publish-service test _http._tcp 80). I’d suggest reviewing and comparing your announcement to that: test._http._tcp.local: type TXT, class IN, cache flush Name: test._http._tcp.local Type: TXT (Text strings) (16) .000 0000 0000 0001 = Class: IN (0x0001) 1... .... .... .... = Cache flush: True Time to live: 4500 (1 hour, 15 minutes) Data length: 1 TXT Length: 0 TXT: _http._tcp.local: type PTR, class IN, test._http._tcp.local Name: _http._tcp.local Type: PTR (domain name PoinTeR) (12) .000 0000 0000 0001 = Class: IN (0x0001) 0... .... .... .... = Cache flush: False Time to live: 4500 (1 hour, 15 minutes) Data length: 2 Domain Name: test._http._tcp.local test._http._tcp.local: type SRV, class IN, cache flush, priority 0, weight 0, port 80, target primary.local Service: test Protocol: _http Name: _tcp.local Type: SRV (Server Selection) (33) .000 0000 0000 0001 = Class: IN (0x0001) 1... .... .... .... = Cache flush: True Time to live: 120 (2 minutes) Data length: 16 Priority: 0 Weight: 0 Port: 80 Target: primary.local primary.local: type A, class IN, cache flush, addr 192.168.1.1 Name: primary.local Type: A (Host Address) (1) .000 0000 0000 0001 = Class: IN (0x0001) 1... .... .... .... = Cache flush: True Time to live: 120 (2 minutes) Data length: 4 Address: 192.168.1.1 (The below record is optional, it makes it so you can browse what types of services exist on the local network) _services._dns-sd._udp.local: type PTR, class IN, _http._tcp.local Name: _services._dns-sd._udp.local Type: PTR (domain name PoinTeR) (12) .000 0000 0000 0001 = Class: IN (0x0001) 0... .... .... .... = Cache flush: False Time to live: 4500 (1 hour, 15 minutes) Data length: 2 Domain Name: _http._tcp.local Hope that helps? Cheers, Trent (@lathiat)
