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

2013-12-04 Thread Simon Kelley

On 04/12/13 01:09, Matthias Andree wrote:


I don't think so - I rather suspect that this is a rare occasion and I
was the first to see and report it.  It would seem we have four
nondefault constraints for the bug to show:

1. IPv6 needs to be enabled on the external interface
2. a global IPv6 needs to be configured, either manually, or
autoconfigured from an external router
3. dnsmasq needs to be installed
4. dnsmasq needs to use --bind-interfaces.




I think you're right. Certainly I was able to reproduce the problem in 
my Freeb=BSD test VM, by adding a globally-routable IPv6 address which 
isn't normally there.



Cheers,

Simon.


___
Dnsmasq-discuss mailing list
Dnsmasq-discuss@lists.thekelleys.org.uk
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss


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

2013-12-03 Thread Simon Kelley

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, 

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

2013-12-03 Thread Matthias Andree
Am 03.12.2013 12:11, schrieb Simon Kelley:

 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 don't think so - I rather suspect that this is a rare occasion and I
was the first to see and report it.  It would seem we have four
nondefault constraints for the bug to show:

1. IPv6 needs to be enabled on the external interface
2. a global IPv6 needs to be configured, either manually, or
autoconfigured from an external router
3. dnsmasq needs to be installed
4. dnsmasq needs to use --bind-interfaces.

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

:)

 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.

I have never bothered to check, yet.

 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?

I'm not aware of one, and address changes do not appear through
devctl(4).  This would best be asked on FreeBSD-hackers or similar lists.


___
Dnsmasq-discuss mailing list
Dnsmasq-discuss@lists.thekelleys.org.uk
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss


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

2013-12-02 Thread 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.


2. Binding IPv6 addresses on FreeBSD does not appear to work properly,
with bind-interfaces option.

3. And the error from 2. does not get properly reported either, the
error code is apparently lost somewhere, or errno gets reset.



OK, that's easy fix, when the bind fails, don't call close() on the 
socket before reporting the error, or save/restore errno.



This is the dnsmasq.conf, domain made up (build configuration is below
in the log of the successful start):


domain-needed
bogus-priv
no-resolv
no-poll
server=127.0.0.1
except-interface=lo0
bind-interfaces
expand-hosts
domain=EXAMPLE.org



This is the interface configuration, with some information masked:


em0: flags=8843UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST  metric 0 mtu 1500
options=9bRXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM
ether ...
inet 192.168.33.14 netmask 0xff00 broadcast 192.168.33.255
inet6 fe80::a00:..ff:fe..:1234%em0 prefixlen 64 scopeid 0x1
inet6 2001::::a00:..ff:fe..:1234 prefixlen 64 autoconf
inet6 2001::::b0e1:f6da:: prefixlen 64 autoconf 
temporary
nd6 options=23PERFORMNUD,ACCEPT_RTADV,AUTO_LINKLOCAL
media: Ethernet autoselect (1000baseTfull-duplex)
status: active
lo0: flags=8049UP,LOOPBACK,RUNNING,MULTICAST  metric 0 mtu 16384
options=63RXCSUM,TXCSUM,RXCSUM_IPV6,TXCSUM_IPV6
inet6 ::1 prefixlen 128
inet6 fe80::1%lo0 prefixlen 64 scopeid 0x4
inet 127.0.0.1 netmask 0xff00
nd6 options=21PERFORMNUD,AUTO_LINKLOCAL
groups: lo



This is the error when running things:


$ LC_ALL=C sudo 
/var/tmp/usr/ports.svn/dns/dnsmasq-devel/work/stage/usr/local/sbin/dnsmasq -d

dnsmasq: failed to create listening socket for 
2001:4dd0:ff00:893e:b0e1:f6da:b2d8:9720%em0: No error: 0


Now, this doesn't help at all, so let's go for details and use truss:


$ LC_ALL=C sudo truss dnsmasq -d 21 | egrep -v close.*ERR#9
mmap(0x0,32768,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANON,-1,0x0) = 34366386176 
(0x800657000)
issetugid(0x800857a60,0x7fffefc8,0x40,0x0,0x800800858a98,0x0) = 0 (0x0)


...


open(/usr/local/etc/dnsmasq.conf,O_RDONLY,0666) = 3 (0x3)
fstat(3,{ mode=-rw-r--r-- ,inode=10763926,size=25245,blksize=16384 }) = 0 (0x0)
read(3,# Configuration file for dnsmasq...,16384) = 16384 (0x4000)
read(3,#dhcp-option-force=208,f1:00:74:...,16384) = 8861 (0x229d)
read(3,0x801c84000,16384)= 0 (0x0)
close(3) = 0 (0x0)
madvise(0x801cd2000,0x1000,0x5,0xd1,0x7fffce00,0x) = 0 (0x0)
madvise(0x801ccf000,0x1000,0x5,0xce,0x7fffce00,0x) = 0 (0x0)
madvise(0x801c84000,0x4000,0x5,0x83,0x7fffce00,0x) = 0 (0x0)
open(/dev/null,O_RDWR,0160002740)= 3 (0x3)
open(/dev/null,O_RDWR,0160002740)= 4 (0x4)
open(/dev/null,O_RDWR,0160002740)= 5 (0x5)
close(3) = 0 (0x0)
close(4) = 0 (0x0)
close(5) = 0 (0x0)
clock_gettime(13,{1385861339.0 })= 0 (0x0)
socket(PF_INET,SOCK_DGRAM,0) = 3 (0x3)
__sysctl(0x7fffd730,0x6,0x0,0x7fffd748,0x0,0x0) = 0 (0x0)
__sysctl(0x7fffd730,0x6,0x801c80400,0x7fffd748,0x0,0x0) = 0 (0x0)
socket(PF_INET6,SOCK_DGRAM,0)= 4 (0x4)
socket(PF_INET,SOCK_DGRAM,0) = 5 (0x5)
ioctl(5,SIOCGIFINDEX,0xd730) = 0 (0x0)
close(5) = 0 (0x0)
ioctl(4,SIOCGIFAFLAG_IN6,0xd7d0) = 0 (0x0)
ioctl(4,SIOCGIFALIFETIME_IN6,0xd7d0) = 0 (0x0)
__sysctl(0x7fffd610,0x6,0x0,0x7fffd628,0x0,0x0) = 0 (0x0)
__sysctl(0x7fffd610,0x6,0x801c80400,0x7fffd628,0x0,0x0) = 0 (0x0)
ioctl(3,SIOCGIFFLAGS,0xd6e0) = 0 (0x0)
ioctl(3,SIOCGIFMTU,0xd6e0)   = 0 (0x0)
socket(PF_INET,SOCK_DGRAM,0) = 5 (0x5)
ioctl(5,SIOCGIFINDEX,0xd730) = 0 (0x0)
close(5) = 0 (0x0)
ioctl(4,SIOCGIFAFLAG_IN6,0xd7d0) = 0 (0x0)
ioctl(4,SIOCGIFALIFETIME_IN6,0xd7d0) = 0 (0x0)

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

2013-12-02 Thread Matthias Andree
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
   699if (family == AF_INET6  setsockopt(fd, IPPROTO_IPV6,
IPV6_V6ONLY, opt, sizeof(opt)) == -1)
   700  goto err;
   701  #endif
   702  
   703if ((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 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).

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

Hope that helps.

Best regards
Matthias

From 2a8601e1eefd19c8bd081e9f2fec363b6ff6da48 Mon Sep 17 00:00:00 2001
From: Matthias Andree matthias.and...@gmx.de
Date: Mon, 2 Dec 2013 22:04:38 +0100
Subject: [PATCH] Really preserve error code when socket setup fails.

---
 src/network.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/network.c b/src/network.c
index 5225ec5..90ab873 100644
--- a/src/network.c
+++ b/src/network.c
@@ -657,7 +657,7 @@ static int make_sock(union mysockaddr *addr, int type, int dienow)
   
   if ((fd = socket(family, type, 0)) == -1)
 {
-  int port;
+  int port, errsav;
   char *s;
 
   /* No error if the kernel just doesn't support this IP flavour */
@@ -667,6 +667,7 @@ static int make_sock(union mysockaddr 

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

2013-12-02 Thread Matthias Andree
-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

Am 02.12.2013 22:13, schrieb Matthias Andree:

 The latter, and I suspect that it might have been any other cache.o file.

... .o file than cache.o.  Not quite clear what's causing it, a
cursory glance over Makefile lets it look innocent to my eye.


-BEGIN PGP SIGNATURE-
Version: GnuPG v1.4.11 (GNU/Linux)

iEYEARECAAYFAlKc+cYACgkQvmGDOQUufZUUpwCgmbWTg7+anmf4GkVNCBKQOz4W
mGUAmgOG2LQ8bGGBEGvPAW5G1y6mZC35
=p1M1
-END PGP SIGNATURE-

___
Dnsmasq-discuss mailing list
Dnsmasq-discuss@lists.thekelleys.org.uk
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss