[Dnsmasq-discuss] 2.68rc4: bind-interfaces, FreeBSD, IPv6 2001:... addr fails and loses error code, parallel build brittle

Simon Kelley simon at thekelleys.org.uk
Tue Dec 3 11:11:02 GMT 2013

On 02/12/13 21:13, Matthias Andree wrote:
> Am 02.12.2013 13:01, schrieb Simon Kelley:
>> On 01/12/13 01:59, Matthias Andree wrote:
>>> Greetings,
>>> testing 2.68rc4, I have found three issues, on FreeBSD 9.2 amd64:
>>> 1. the Makefiles might not thoroughly list all dependencies required to
>>> build the dnsmasq executable; I found my build miss cache.o when linking
>>> (compiling with make -j + high number), re-running make immediately
>>> after the failure "solved" the problem.
>>> I am using a local UFS file system, so no NFS time skew.
>>> I am using GNU make 3.82.
>> By "miss cache.o" do you meant that cache.o was not included in the link
>> command line, or that the link failed because cache.o had not been
>> built. This is mysterious, and there's nothing different about cache.o
>> versus the other object files.
> The latter, and I suspect that it might have been any other cache.o file.
>> I'd be interested to know the status of those addresses, and Duplicate
>> Address Detection, since that's the best explanation I have of the
>> source of that error return. Is it possible to turn DAD off, and see if
>> that fixes things?
> Yes, but it is neither the culprit nor does it fix things.
>> I'm also interested in what's happening in bpf.c in the interface
>> enumeration code:
>>           ifr6.ifr_addr = *((struct sockaddr_in6 *) addrs->ifa_addr);
>>                if (fd != -1&&  ioctl(fd, SIOCGIFAFLAG_IN6,&ifr6) != -1)
>>                  {
>>                    if (ifr6.ifr_ifru.ifru_flags6&  IN6_IFF_TENTATIVE)
>>                      flags |= IFACE_TENTATIVE;
>> Should set IFACE_TENTATIVE in flags if the interface is still doing DAD.
> The address is marked with only the IN6_IFF_AUTOCONF flag.
> IN6_IFF_TENTATIVE in particular is unset.
> On the second another 2001:... address, I have automatic | temporary
> (private).  Meaning that the ifconfig output renders the interface flags
> quite well.  But that's not the issue here.
> The flags variable you pass through the callback on line 199 in bpf.c
> ends up as 0 for these two aliases on em0.
> Anyways I debugged this a bit more, and in network.c you have:
>     698	#ifdef HAVE_IPV6
>     699	  if (family == AF_INET6&&  setsockopt(fd, IPPROTO_IPV6,
> IPV6_V6ONLY,&opt, sizeof(opt)) == -1)
>     700	    goto err;
>     701	#endif
>     702	
>     703	  if ((rc = bind(fd, (struct sockaddr *)addr, sa_len(addr))) == -1)
>     704	    goto err;
> When this is run on the 2001:. addresses, addr->in6.sin6_scope_id is not
> 0.  Setting this to 0 only on the 2001:... addresses makes the bind
> succeed, and presents me with:
>> dnsmasq: started, version 2.68rc4-2-g0861921 cachesize 150
>> dnsmasq: compile time options: IPv6 GNU-getopt no-DBus no-i18n no-IDN DHCP DHCPv6 no-Lua TFTP no-conntrack no-ipset auth
>> dnsmasq: LOUD WARNING: listening on 2001:BLAH:BLAH:893e:a00:MAC:ADDR:HERE may accept requests via interfaces other than em0
>> dnsmasq: LOUD WARNING: use --bind-dynamic rather than --bind-interfaces to avoid DNS amplification attacks via these interface(s)
>> dnsmasq: using nameserver
>> dnsmasq: read /etc/hosts - 5 addresses
> Now we're getting somewhere, apparently FreeBSD chokes if you present a
> nonzero sin6_scope_id with a regular unicast address, rather than a
> link-local special address (which requires the interface index), whereas
> Linux appears to ignore it.
> Could you double-check iface_allowed_v6() and the network enumeration
> code that calls it, and the code in network.c:703 that calls bind()?
> Either needs to zero out the scope_id for non-link-local i'faces.

That looks like a very good diagnosis: zeroing the scope_id in the 
appropriate cases should be easy. I wonder why this has just struck, the 
code has been like that for some time, and never previuosly hit a 
problem. FreeBSD change?

I'm thinking of having a small tattoo, in a visible (to me) place that 
reads "REMEMBER: IPv6 is not IPv4".

> That aside, I am not sure what this LOUD WARNING is about here, and if
> it applies to FreeBSD (it would seem Linux can do reverse path checking,
> too, and reject martians if the stuff arrives on the wrong interface's
> ingress).

It's not a martian problem, it's the Weak End System Model which is used 
by Linux. I don't know if that's used by FreeBSD.

When --bind-interfaces in in use dnsmasq --interface=em0 becomes 
functionally equivalent to dnsmasq --listen-address=<address_of_em0>
With a weak end system, packets arriving on _any_ interface will be 
accepted if their destination address in an address of em0. This 
equivalence is because --bind-interfaces mode is intended to work on 
platforms which don't support the API which returns the arrival 
interface of a the packet, so the only filtering of the bind()ing of the 

The standard fix is to use --bind-dynamic, which can rely  on the 
existence of the extended API. Unfortunately that doesn't work on 
FreeBSD because it also relies on a a method of getting asynchronous 
events when interfaces/address come and go. Does FreeBSD have an 
equivalent of the Linux netlink socket?

(OpenBSD, last time I checked, doesn't support any of this API, so 
having a least-common-denominator fallback is still needed).

Having been made to think about this again, I've just realised that the 
above paragraph only applies to IPv4: the IPV6_PKTOPTIONS API is 
standard and available on every platform for IPv6. It would make sense 
to always check the arrival interface for IPv6 and suppress that 
warning. Since globally-routable IPv6 addresses are more prevalent that 
globally-routable IPv4 addresses, that would be valuable.

>> I'll commit a fix for the simple errno problem, to make things easier.
> Unfortunately, that does not appear to work either, I still get
> "dnsmasq: failed to create listening socket for 2001:...c258%em0: No
> error: 0". (I am on git master, which is one commit ahead of 3dffbc3eb).
> I am attaching an incremental patch (use "git am" to apply it) to the
> current Git master that fixes the problem for me. It merely extends the
> scope of the errsav copy of the actual errno code.
> (Sending a Bcc: to Simon in case the list driver strips it.)

Yes, that makes much more sense.
> Hope that helps.

I does, a lot. Many thanks for your efforts. Expect changes in git 
addressing your points very soon.



> Best regards
> Matthias
> _______________________________________________
> Dnsmasq-discuss mailing list
> Dnsmasq-discuss at lists.thekelleys.org.uk
> http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss

More information about the Dnsmasq-discuss mailing list