mdns-scan complains that IP_ADD_MEMBERSHIP failed

Last weekend I had to use a video projector via Google cast or chromecast or whatever it's called this month – it was mounted at the ceiling and was unreachable by cables.

What I could work out about Google cast from a few web searches sounded like it should be simple: encode what's on the local screen to a video and then transmit that to some more or less bespoke endpoint through – I think – Secure Reliable Transport, a UDP-based protocol for which there's a Debian package called srt-tools.

Whether or not that's roughly right, what I failed to answer is: Where do you transmit to? It seems the way to figure that out is to ask zeroconf alias Bonjour the right questions, and that in turn seems to require multicasting DNS-ish requests and then collecting responses from devices that reply to these multicasts. Aw! If only avahi – the usual mDNS implementation on Linux – wasn't among the first things I purge from machines if I find it.

While trying to nevertheless cobble something together that would tell me where to send my stream to I got an interesting error message when I experimentally ran mdns-scan:

IP_ADD_MEMBERSHIP failed: No such device

This was while I was connected to the projector's built-in Wifi access point. And I didn't have the foggiest idea what the thing was saying. Search engines didn't bring up satisfying explanations (although there was some unspecific mumbling about “routes”). So, I straced the thing to see what syscalls it does before giving up:

$ strace mdns-scan
[the dynamic linker in action]
ugetrlimit(RLIMIT_STACK, {rlim_cur=8192*1024, rlim_max=RLIM_INFINITY}) = 0
munmap(0xf7f13000, 132486)              = 0
socket(AF_INET, SOCK_DGRAM, IPPROTO_IP) = 3
setsockopt(3, SOL_IP, IP_MULTICAST_TTL, [255], 4) = 0
setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
bind(3, {sa_family=AF_INET, sin_port=htons(5353), sin_addr=inet_addr("224.0.0.251")}, 16) = 0
setsockopt(3, SOL_IP, IP_ADD_MEMBERSHIP, {imr_multiaddr=inet_addr("224.0.0.251"), imr_interface=inet_addr("0.0.0.0")}, 12) = -1 ENODEV (No such device)
write(2, "IP_ADD_MEMBERSHIP failed: No suc"..., 41IP_ADD_MEMBERSHIP failed: No such device
) = 41
close(3)                                = 0
exit_group(1)                           = ?

– failing after so few syscalls is actually brilliant. Try strace on your average web browser or even your python interpreter and you know what I mean.

And while I don't really know much about multicasting, this gave me an idea what was going on. You see, the projector hadn't set a default route. My box's routing table was simply:

$ ip route
192.168.2.0/24 dev wlan0 proto kernel scope link src 192.168.2.32

I guess that's rather typical, and that's why I'm writing this: I'd expect other people trying Google cast or Airplay to projectors may run into that same problem.

The reason this is a problem is that mdns-scan wants to (I think; don't believe me without researching further) subscribe to the address 224.0.0.251 via some network interface. That particular IP address looks less crazy than it is, because it's a multicast address, which makes it mean something rather special, and this one is special special because it basically means “I want to see multicast DNS packets floating around on the local network” (and send them to everyone using the same router as I do). Saying this means that the machine has to have an idea where to send packets to, and with the routing table the projector's DHCP server set up, it felt it didn't know that. I have to admit I have not quite worked out just why it felt that, but I'm rather confident that's why the setsockopt above failed.

In that special situation – when you are not connected to the internet anyway – it is safe to just set the default route to the projector:

$ ip route add default via 192.168.2.1 dev wlan0

(where you will probably have to change the IP address to whatever your projector binds to; it's almost certainly the address of the DHCP server on the projector's access point, which you'll find in your syslog). This is enough to let mdns-scan do its multicasting magic, and indeed it now yielded a handle for the chromecasting service.

But that still was not enough to figure out where to srt-live-transmit my video stream to, and hence I didn't get to improvise screen mirroring in the time I had before the event started. I eventually projected using a Windows (well: at least not Android…) box with a silly chromecast dongle that came with the projector and had some nasty driver software for the dongle on some built-in USB mass storage.

Regrettably (or fortunately, if you want), I don't have access to the device any more, so I cannot continue my chromecast hacking. If you are aware of a little script that does the zeroconf queries and connection setup in a few lines, please let me know: It would be nice to be prepared when next I encounter one of these beasts.

Kategorie: edv

Letzte Ergänzungen