[avahi] avahi-core on Linux without netlink?
Jonathan Bagg
jbagg at lenbrook.com
Mon Feb 28 15:46:04 UTC 2022
Thank you Trent.
My use case --> I have been using avahi-core on Android for NDK (c++)
apps. Android's NsdManager (java) has too many bugs / is not reliable.
Maybe I can add into avahi-core an api to call when the network
interfaces change as you suggest. Maybe
avahi_s_interface_add(something)
avahi_s_interface_remove(something)
It really sucks to do this. Google should ship avahi-client for NDK stuff.
Jon
On 2022-02-27 8:11 p.m., Trent Lloyd wrote:
> Yes this is currently correct. Avahi needs a way to see a list of interfaces and IP addresses as well to monitor when they are added and removed. Currently the only interface for that on Linux is netlink.
>
> If you want to go without it you’d have to write a replacement iface-*.c code to leverage whatever APIs are available.
>
> What’s your use case?
>
> Trent
>
>> On 28 Feb 2022, at 1:47 am, Jonathan Bagg <jbagg at lenbrook.com> wrote:
>>
>> Hello,
>>
>> I have built libavahi-core.a from source without netlink support on Linux (x86 Debian 11). Why --> Google has disabled binding to a netlink socket in api >= 30. Unfortunately my program is not able to publish or browse for services without netlink enabled in avahi-core. Is this correct behaviour? I noticed iface-none.c is built instead of iface-linux.c.
>>
>> Jon
>>
>>> On 2021-12-07 8:24 p.m., Trent Lloyd wrote:
>>> Hi Folkert,
>>>
>>>>> On 8 Dec 2021, at 4:56 am, folkert <folkert at vanheusden.com> 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://linkprotect.cudasvc.com/url?a=https%3a%2f%2fvps001.vanheusden.com%2f~folkert%2fmdns.pcap&c=E,1,qAnUYiH7cFCdxQbDZpGLALJ3CssMNFzEVwiE1YbVHM6xWACOIfv0bXq4NyQO47Se-scGGdgXM8Y-4LPX_zaw-lMTYcZTObE8F7JZtvBCze4WWoAqIg,,&typo=1
>>>>> (text dump: https://linkprotect.cudasvc.com/url?a=https%3a%2f%2fvps001.vanheusden.com%2f~folkert%2fmdns.txt&c=E,1,j_MXzszdG-MCfApSpw2sf4M8LBrQJcvTlDZUHKUshzPaBaT2VINalQ-vLxTh1PcaTI7hzfBzJ8GIdmcqriVdhknuL4iP35MAIF2fNwH9jQZ_2tNyB-AAdodHqJs,&typo=1 )
>>>>>
>>>>> 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://linkprotect.cudasvc.com/url?a=https%3a%2f%2fdatatracker.ietf.org%2fdoc%2fhtml%2frfc6762%23section-10.2&c=E,1,hRneuq7gmccKO3LOVORaP2tWQygWE5bJiKLRQha1JzYmzqty-tJg-1qQYtkUu_e_UjO2kU6ACgPcwFQz4fxni2UFlKtmaHdTPZhuKufxrZxAWjuemctkl_UUwB8,&typo=1)
>>>
>>> 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)
>>>
More information about the avahi
mailing list