Search code examples
csocketsposixbonjourmdns

POSIX Bonjour/mDNSResponder test examples report "bind: Address already in use" on Ubuntu, but not Debian


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


Solution

  • 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.