Hello,

This isn't strictly about Avahi, but I have some questions to ask and 
assertions I'd like to validate. What's led me down the rabbit hole of 
Zeroconf, mDNS, DNS-SD, and friends is out of interest in making stuff easy to 
use. For a specific example, GeoClue is configured to look for services of type 
_nmea-0183._tcp to find services providing real-time geopositioning 
information. This is a one-way data feed; the server simply sends a few lines 
of US-ASCII every second and anything sent by the client can be ignored. Using 
UDP over multicast would be a lot more efficient and better support the need 
for low latency, so I've been researching how to do this. Many of you likely 
already know much of what follows, but I'd like to know if I got anything wrong.

Pertinent standards such as POSIX at 
https://pubs.opengroup.org/onlinepubs/9799919799/functions/V2_chap02.html#tag_16_10_20_04
 define much of what's needed to use IPv6 multicast, including the 
IPV6_JOIN_GROUP socket options. When some protocol or application always uses 
some fixed multicast address that can be determined ahead of time, like the one 
for mDNS given by 
https://www.iana.org/assignments/ipv6-multicast-addresses/ipv6-multicast-addresses.xhtml#xpointer(/html/body//table[@id="table-link-local"]/tbody/tr/td[text()="mDNSv6"]/..)
 then this may be all that is needed. However many applications only need a 
transient multicast address, or they're too esoteric to warrant an IANA 
registration (perhaps because interoperability with another implementation 
isn't a concern). The question then is how should one "make up" a multicast 
address on-the-fly?
One perk of using these IANA-assigned addresses is that the protocol or purpose 
for some multicast group is already tied to the address. If you want to send a 
message using SIP to anyone on your link that's listening, just send a datagram 
to FF02::175. This differs when using a dynamic multicast address. Consider, 
for my use case, if I had a GNSS receiver getting geolocation information and 
wanted to share it on the local link as a server. Even if I come up with a 
multicast address on-the-fly for this purpose, how will clients know to find 
me? Fortunately this is just a service discovery problem and Avahi can solve it 
in the same way as for the TCP service case: I can publish _nmea-0183._udp 
DNS-SD information and based on the IPv6 address format it's clearly a 
multicast address. Therefore any prospective clients can just join the group 
and listen for datagrams on the port designated by the SRV record.
There are, of course, other methods of announcing and discovering services than 
just DNS-SD. Any of those mechanisms ought to work to announce the birth of a 
multicast group for some use case, even in conjunction with DNS-SD, so it's 
easy to make such a service discoverable.

That means there's only one problem for application writers left: how do you 
get a dynamic multicast address anyway? An application wishing to make a new 
group should have a convenient way to do this, but as far as I know, there's 
not any way for an application on GNU/Linux to do this correctly. I couldn't 
even find a maintained third-party library after searching. There are a couple 
different network protocols to solve this address allocation problem (more on 
those in a moment), but is there any libre code that's able to use any of them?
The informational RFC 2771 (from the year 2000, before I was born!) articulates 
"An Abstract API for Multicast Address Allocation". This document only uses 
pseudocode and is intentionally programming-language-agnostic, but describes 
the considerations needed to make an API for application instances to get 
multicast addresses to call their very own. Despite its age, that document 
appears to still be a very good role model for what an API should look like. It 
also demonstrates such an API can be designed so the particular means by which 
an address is allocated is an implementation detail. Application writers 
generally aren't concerned with how an appropriate address is obtained and for 
the sake of portability this should be done however the operating system or 
environment sees fit.
The most well-established scheme for multicast address allocation is MADCAP, 
which works in a DHCP-like way with a central server that's authoritative over 
the scope in question and gives out leases. This looks like the way Windows has 
gone, and in fact, Microsoft has a C/C++ API for this: 
https://learn.microsoft.com/en-us/windows/win32/api/madcapcl/ and despite the 
name of the header, the function names read as "multicast request address", 
"multicast release address", and so forth. This is more DHCP-like than 
SLAAC-like which one might say is ugly in the year 2025, but if that works for 
them (and I do believe it does in a Windows Server/Active Directory business 
environment with Windows machines providing compatible DHCP and MADCAP server 
implementations), that's good for them.
        That Windows API doesn't seem to have any MADCAP assumptions baked into 
it and instead is more generic like RFC 2771, so if it helps adoption by libre 
applications, maybe an API-compatible shim could be helpful? (I wonder if 
Winelib—which is like Cygwin in reverse, to allow compiling Windows application 
source code for Unix-like systems—has this.)

As recently as this year the informational internet draft "Multicast Lessons 
Learned from Decades of Deployment Experience" has analyzed what's gone wrong 
and caused trouble for uptake of multicast outside specialized environments. At 
https://www.ietf.org/archive/id/draft-ietf-pim-multicast-lessons-learned-05.html#name-dynamic-multicast-group-add
 the authors make quite clear that MADCAP isn't the goal to set sight on 
anymore: "It was later determined that multicast addresses really should be 
dynamically assigned by a decentralized, and zero configuration, protocol for 
many of todays environments." The two strongest options for moving forward are 
the Zeroconf Multicast Address Allocation Protocol (ZMAAP), which has been in 
various drafts for decades, and the new Group Address Allocation Protocol 
(GAAP). Hereafter I'll focus on the former, but I do wonder where in the 
GNU/Linux network stack an implementation of the latter might sit.

A very old draft for ZMAAP is at 
https://datatracker.ietf.org/doc/draft-ietf-zeroconf-zmaap/ but the only reason 
I mention this older version is because "An API for the Zeroconf Multicast 
Address Allocation Protocol (ZMAAP)" 
https://datatracker.ietf.org/doc/draft-ietf-zeroconf-zmaap-api/ was also 
jointly published. That draft builds on the "abstract API" mentioned before and 
actually makes it concrete with C and Java interfaces. Please correct me if I'm 
wrong, but to the best of my knowledge there aren't any actual implementations 
of this, at least not surviving ones for GNU/Linux. The document is slightly 
misnamed; a more accurate title would be something like "An API for Mulicast 
Address Allocation with Due Consideration for the Capabilities of ZMAAP". As 
they say, "It should be transperant [sic] to the API whether the allocations 
are done using ZMAAP, MADCAP or some other mechanism."
From a brief skim the C API looks decent, except their data structures use some 
not-POSIX-like conventions. In the 25 years since the document was published a 
very good consensus (even with Windows) has been formed about the use of data 
types and modernizing the interfaces would be nice. In particular:
• 'struct sockaddr' is used with the intent of holding both IPv4 and IPv6 
addresses; 'struct sockaddr_storage' should be used instead
• they store the address family separately from the socket address structures 
which is unnecessary, but also define the constants '1' for IPv4 and '2' for 
IPv6; the (struct sockaddr){}.sa_family member should suffice and allow using 
AF_INET, AF_INET6, etc. constants as usual
But in general, this API is the closest thing to exactly what I need to write a 
nice multicast application. (Well, an actual implementation will be needed too, 
but don't ruin my dream…)
Both that draft for ZMAAP and the one for the proposed C/Java APIs are from 
2000 and long dead, but an active standards-track internet draft (yes, not 
expired!) for the ZMAAP protocol is available at 
https://datatracker.ietf.org/doc/draft-ietf-pim-ipv6-zeroconf-assignment/ and 
there's also a statement of exactly the problems it solves at 
https://datatracker.ietf.org/doc/html/draft-ietf-pim-zeroconf-mcast-addr-alloc-ps

In their usage of the term, they use "zeroconf" basically as a synonym for 
Multicast DNS. There are other tools under the umbrella of zero configuration, 
and strictly speaking, the alternative Group Address Allocation Protocol (GAAP) 
is probably one of them. ZMAAP really should be on the radar of Avahi folks, 
and in fact, I think the right place for an implementation is in Avahi 
directly. The method involved is basically to synthesize a name under the 
'eth-addr.arpa.' DNS zone and use Multicast DNS with the appropriate scope to 
detect collisions. Because it's a bad idea to try running multiple mDNS 
stacks—as remarked in avahi-daemon.conf(5)—any ZMAAP implementation will need 
to go through whatever daemon has taken up responsibility for mDNS, be it 
Avahi, systemd-resolved, or otherwise.
Additionally, as I described much earlier in this mail with regards to the 
"service discovery problem" for applications wanting to join dynamic multicast 
groups that might've already been created, many multicast applications will 
want Avahi's help to publish DNS-SD records anyway. Lastly, for some use cases 
where you want everyone to converge on the same dynamic multicast group 
(perhaps a multiplayer video game that lets players drop in and out at any 
time), there could be race conditions or quirks from separating checks for an 
established multicast group for an application versus deciding to allocate an 
address and spawn your own. (For example an application may ask Avahi to "see 
if there's already a group for _bingo._udp, but if there's not, then I must be 
the first one here so let's set one up".)

In conclusion, I've been puzzled trying to make a mostly-custom application 
using multicast and I asked "How do other libre applications pick their 
multicast addresses for their own usage?". The conclusion I've drawn is "They 
don't." I couldn't find any modern information about real-world existing 
practice for these sorts of problems, so I've espoused it here for future 
reference and so you can tell me what I got wrong. Otherwise it looks like 
Avahi should provide an API for multicast address allocation, concentrating on 
ZMAAP, and which need not match the existing and proposed APIs but may still 
borrow inspiration from them. I don't mean to "voluntell" the Avahi developers 
what to do but instead articulate a problem statement and solution idea so it 
can be consciously accepted or declined.

Thanks,
John

Attachment: signature.asc
Description: This is a digitally signed message part

Attachment: smime.p7s
Description: S/MIME cryptographic signature

Reply via email to