[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 127.0.0.1#53
>> 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
socket.
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.
Cheers,
Simon.
>
> 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