0

When building the Apple's implementation of mDNS, aka. Bonjour, aka. mDNSResponder for a posix system (http://www.opensource.apple.com/tarballs/mDNSResponder/) [*]

  • On a clean Ubuntu 14.04 build box (with only build-essentials, g++), the compiled examples fail to work, and report "bind: Address already in use".

  • On a clean Debian 7 build box (with only build-essentials, g++), the compiled examples work, and do not report "bind: Address already in use".

What is going on here?

[*] which... is just riddled with bugs. For sanity, I suggest using versions 333.10, or 541, and applying patches from the umondo project: https://github.com/tklab-tud/umundo/tree/master/contrib/archives

swalog
  • 4,069
  • 3
  • 27
  • 57

2 Answers2

0

The problem is due to the following difference in /usr/include/asm-generic/socket.h

The socket.h in question is part of the linux-libc-dev package.

In Debian, socket.h is from version 3.2.65 of linux-libc-dev, and contains contains the commented line

/* To add :#define SO_REUSEPORT 15 */

On Ubuntu, linux-libc-dev is version 3.13.0. socket.h. Here, that line is no longer commented out:

#define SO_REUSEPORT    15

Of course, the problem is not with linux-libc-dev, but the use of this macro, in mDNSPosix.c, in particular, the lines:

#if defined(SO_REUSEPORT)
    err = setsockopt(*sktPtr, SOL_SOCKET, SO_REUSEPORT, &kOn, sizeof(kOn));
#elif defined(SO_REUSEADDR)
    err = setsockopt(*sktPtr, SOL_SOCKET, SO_REUSEADDR, &kOn, sizeof(kOn));
#else
    #error This platform has no way to avoid address busy errors on multicast.
#endif

By just swapping the order, to prioritize SO_REUSEADDR, there is no longer a socket binding issue. I.e.:

#if defined(SO_REUSEADDR)
    err = setsockopt(*sktPtr, SOL_SOCKET, SO_REUSEADDR, &kOn, sizeof(kOn));
#elif defined(SO_REUSEPORT)
    err = setsockopt(*sktPtr, SOL_SOCKET, SO_REUSEPORT, &kOn, sizeof(kOn));
#else
    #error This platform has no way to avoid address busy errors on multicast.
#endif

Note: This change has not been tested in BSD, which, if I understand correctly, should perhaps keep the priority in the order it was.

swalog
  • 4,069
  • 3
  • 27
  • 57
  • The reason I'm adding this here, is that this problem, and several other "this can't possible have passed compilation"-bugs (looking at you `mDNSShared/dnssd_clientshim.c`), has persisted in the bonjour library for many years. Making it doubtful that a bugreport will fix another such error in any timely manner. – swalog Feb 27 '15 at 08:01
0

You're running into the differences between SO_REUSEADDR AND SO_REUSEPORT.

SO_REUSEPORT was introduced in later Linux kernels and it appears the Ubuntu system image has support for it. Take a look at this question for all you could ever want to know about REUSADDR/REUSEPORT.

The behavioral differences between REUSEADDR and REUSEPORT are that REUSEPORT places more restrictions on the sockets trying to reuse the same port: they all have to have the option set and exist within the same process. That's not the case with REUSEADDR.

Is it possible your Ubuntu image is also running another mDNS daemon like avahi? You can run netstat to diagnose the other bound sockets in the system to identify the port collisions

Community
  • 1
  • 1
Joel Cunningham
  • 591
  • 4
  • 16