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=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST>  metric 0 mtu 1500
        options=9b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM>
        ether ...
        inet 192.168.33.14 netmask 0xffffff00 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=23<PERFORMNUD,ACCEPT_RTADV,AUTO_LINKLOCAL>
        media: Ethernet autoselect (1000baseT<full-duplex>)
        status: active
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST>  metric 0 mtu 16384
        options=600003<RXCSUM,TXCSUM,RXCSUM_IPV6,TXCSUM_IPV6>
        inet6 ::1 prefixlen 128
        inet6 fe80::1%lo0 prefixlen 64 scopeid 0x4
        inet 127.0.0.1 netmask 0xff000000
        nd6 options=21<PERFORMNUD,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 2>&1 | egrep -v close.*ERR#9
mmap(0x0,32768,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANON,-1,0x0) = 34366386176 
(0x800657000)
issetugid(0x800857a60,0x7fffffffefc8,0x40,0x0,0xffff800800858a98,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,0x7fffffffce00,0xffffffff) = 0 (0x0)
madvise(0x801ccf000,0x1000,0x5,0xce,0x7fffffffce00,0xffffffff) = 0 (0x0)
madvise(0x801c84000,0x4000,0x5,0x83,0x7fffffffce00,0xffffffff) = 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.000000000 })        = 0 (0x0)
socket(PF_INET,SOCK_DGRAM,0)                     = 3 (0x3)
__sysctl(0x7fffffffd730,0x6,0x0,0x7fffffffd748,0x0,0x0) = 0 (0x0)
__sysctl(0x7fffffffd730,0x6,0x801c80400,0x7fffffffd748,0x0,0x0) = 0 (0x0)
socket(PF_INET6,SOCK_DGRAM,0)                    = 4 (0x4)
socket(PF_INET,SOCK_DGRAM,0)                     = 5 (0x5)
ioctl(5,SIOCGIFINDEX,0xffffd730)                 = 0 (0x0)
close(5)                                         = 0 (0x0)
ioctl(4,SIOCGIFAFLAG_IN6,0xffffd7d0)             = 0 (0x0)
ioctl(4,SIOCGIFALIFETIME_IN6,0xffffd7d0)         = 0 (0x0)
__sysctl(0x7fffffffd610,0x6,0x0,0x7fffffffd628,0x0,0x0) = 0 (0x0)
__sysctl(0x7fffffffd610,0x6,0x801c80400,0x7fffffffd628,0x0,0x0) = 0 (0x0)
ioctl(3,SIOCGIFFLAGS,0xffffd6e0)                 = 0 (0x0)
ioctl(3,SIOCGIFMTU,0xffffd6e0)                   = 0 (0x0)
socket(PF_INET,SOCK_DGRAM,0)                     = 5 (0x5)
ioctl(5,SIOCGIFINDEX,0xffffd730)                 = 0 (0x0)
close(5)                                         = 0 (0x0)
ioctl(4,SIOCGIFAFLAG_IN6,0xffffd7d0)             = 0 (0x0)
ioctl(4,SIOCGIFALIFETIME_IN6,0xffffd7d0)         = 0 (0x0)
__sysctl(0x7fffffffd610,0x6,0x0,0x7fffffffd628,0x0,0x0) = 0 (0x0)
__sysctl(0x7fffffffd610,0x6,0x801cb1400,0x7fffffffd628,0x0,0x0) = 0 (0x0)
ioctl(3,SIOCGIFFLAGS,0xffffd6e0)                 = 0 (0x0)
ioctl(3,SIOCGIFMTU,0xffffd6e0)                   = 0 (0x0)
socket(PF_INET,SOCK_DGRAM,0)                     = 5 (0x5)
ioctl(5,SIOCGIFINDEX,0xffffd730)                 = 0 (0x0)
close(5)                                         = 0 (0x0)
ioctl(4,SIOCGIFAFLAG_IN6,0xffffd7d0)             = 0 (0x0)
ioctl(4,SIOCGIFALIFETIME_IN6,0xffffd7d0)         = 0 (0x0)
__sysctl(0x7fffffffd610,0x6,0x0,0x7fffffffd628,0x0,0x0) = 0 (0x0)
__sysctl(0x7fffffffd610,0x6,0x801cb1400,0x7fffffffd628,0x0,0x0) = 0 (0x0)
ioctl(3,SIOCGIFFLAGS,0xffffd6e0)                 = 0 (0x0)
ioctl(3,SIOCGIFMTU,0xffffd6e0)                   = 0 (0x0)
socket(PF_INET,SOCK_DGRAM,0)                     = 5 (0x5)
ioctl(5,SIOCGIFINDEX,0xffffd730)                 = 0 (0x0)
close(5)                                         = 0 (0x0)
ioctl(4,SIOCGIFAFLAG_IN6,0xffffd7d0)             = 0 (0x0)
ioctl(4,SIOCGIFALIFETIME_IN6,0xffffd7d0)         = 0 (0x0)
__sysctl(0x7fffffffd610,0x6,0x0,0x7fffffffd628,0x0,0x0) = 0 (0x0)
__sysctl(0x7fffffffd610,0x6,0x801cb1400,0x7fffffffd628,0x0,0x0) = 0 (0x0)
ioctl(3,SIOCGIFFLAGS,0xffffd6e0)                 = 0 (0x0)
ioctl(3,SIOCGIFMTU,0xffffd6e0)                   = 0 (0x0)
socket(PF_INET,SOCK_DGRAM,0)                     = 5 (0x5)
ioctl(5,SIOCGIFINDEX,0xffffd730)                 = 0 (0x0)
close(5)                                         = 0 (0x0)
ioctl(4,SIOCGIFAFLAG_IN6,0xffffd7d0)             = 0 (0x0)
ioctl(4,SIOCGIFALIFETIME_IN6,0xffffd7d0)         = 0 (0x0)
__sysctl(0x7fffffffd610,0x6,0x0,0x7fffffffd628,0x0,0x0) = 0 (0x0)
__sysctl(0x7fffffffd610,0x6,0x801cb1400,0x7fffffffd628,0x0,0x0) = 0 (0x0)
ioctl(3,SIOCGIFFLAGS,0xffffd6e0)                 = 0 (0x0)
ioctl(3,SIOCGIFMTU,0xffffd6e0)                   = 0 (0x0)
close(4)                                         = 0 (0x0)
__sysctl(0x7fffffffd730,0x6,0x0,0x7fffffffd748,0x0,0x0) = 0 (0x0)
__sysctl(0x7fffffffd730,0x6,0x801c81400,0x7fffffffd748,0x0,0x0) = 0 (0x0)
socket(PF_INET,SOCK_DGRAM,0)                     = 4 (0x4)
ioctl(4,SIOCGIFINDEX,0xffffd730)                 = 0 (0x0)
close(4)                                         = 0 (0x0)
__sysctl(0x7fffffffd610,0x6,0x0,0x7fffffffd628,0x0,0x0) = 0 (0x0)
__sysctl(0x7fffffffd610,0x6,0x801c81400,0x7fffffffd628,0x0,0x0) = 0 (0x0)
ioctl(3,SIOCGIFFLAGS,0xffffd6e0)                 = 0 (0x0)
ioctl(3,SIOCGIFMTU,0xffffd6e0)                   = 0 (0x0)
socket(PF_INET,SOCK_DGRAM,0)                     = 4 (0x4)
ioctl(4,SIOCGIFINDEX,0xffffd730)                 = 0 (0x0)
close(4)                                         = 0 (0x0)
__sysctl(0x7fffffffd610,0x6,0x0,0x7fffffffd628,0x0,0x0) = 0 (0x0)
__sysctl(0x7fffffffd610,0x6,0x801c81400,0x7fffffffd628,0x0,0x0) = 0 (0x0)
ioctl(3,SIOCGIFFLAGS,0xffffd6e0)                 = 0 (0x0)
ioctl(3,SIOCGIFMTU,0xffffd6e0)                   = 0 (0x0)
close(3)                                         = 0 (0x0)
socket(PF_INET,SOCK_DGRAM,0)                     = 3 (0x3)
setsockopt(0x3,0xffff,0x4,0x7fffffffd8d4,0x4,0xffffffff) = 0 (0x0)
fcntl(3,F_GETFL,)                                = 2 (0x2)
fcntl(3,F_SETFL,O_NONBLOCK|0x2)                  = 0 (0x0)
bind(3,{ AF_INET 192.168.33.14:53 },16)          = 0 (0x0)
socket(PF_INET,SOCK_STREAM,0)                    = 4 (0x4)
setsockopt(0x4,0xffff,0x4,0x7fffffffd8d4,0x4,0xffffffff) = 0 (0x0)
fcntl(4,F_GETFL,)                                = 2 (0x2)
fcntl(4,F_SETFL,O_NONBLOCK|0x2)                  = 0 (0x0)
bind(4,{ AF_INET 192.168.33.14:53 },16)          = 0 (0x0)
listen(0x4,0x5,0x10,0x7fffffffd8d4,0x4,0xffffffff) = 0 (0x0)
socket(PF_INET6,SOCK_DGRAM,0)                    = 5 (0x5)
setsockopt(0x5,0xffff,0x4,0x7fffffffd8d4,0x4,0x0) = 0 (0x0)
fcntl(5,F_GETFL,)                                = 2 (0x2)
fcntl(5,F_SETFL,O_NONBLOCK|0x2)                  = 0 (0x0)
setsockopt(0x5,0x29,0x1b,0x7fffffffd8d4,0x4,0x0) = 0 (0x0)
bind(5,{ AF_INET6 [2001:....:....:....:b0e1:f6da:....:....]:53 },28) ERR#49 
'Can't assign requested address'

Corresponding to EADDRNOTAVAIL.  Removing the alias causes the same
issue on the other 2001:... address.  Removing both 2001:... aliases
lets dnsmasq start up, and lsof -i:53 -n gives this:

named    889 bind   20u  IPv4 0xfffffe0005d823d0      0t0  TCP 127.0.0.1:domain 
(LISTEN)
named    889 bind  512u  IPv4 0xfffffe0005b590c0      0t0  UDP 127.0.0.1:domain
dnsmasq 5727 root    3u  IPv4 0xfffffe0005b59890      0t0  UDP 
192.168.33.14:domain
dnsmasq 5727 root    4u  IPv4 0xfffffe006fa6eb70      0t0  TCP 
192.168.33.14:domain (LISTEN)
dnsmasq 5727 root    5u  IPv6 0xfffffe0005b0d2d0      0t0  UDP 
[fe80::a00:..ff:fe..:1234%em0]:domain
dnsmasq 5727 root    6u  IPv6 0xfffffe006f253000      0t0  TCP 
[fe80::a00:..ff:fe..:1234%em0]:domain (LISTEN)

Not sure what's going on there when it's trying to bind 2001:... addresses.


I think I know. I've seen this before: it occurs when you try and bind() a socket to a local address which is still undergoing Duplicate Address Detection.

This came up some time ago, and code was added to detect interface addresses in this state (by looking at the flags) and defer bind()ing them until DAD was complete.

What's confusing is that code _was_ only complete on Linux: the ability to determine if an address is still in DAD state was missing on *BSD, and it always assumed that DAD was complete, so I'd expect to see the problem you're seeing with older releases. From 2.67, the code is included for *BSD, so it should be OK, or at least not attempt to bind() at this point.



Now, if I remove bind-interfaces, I get:

dnsmasq: started, version 2.67 cachesize 150
dnsmasq: compile time options: IPv6 GNU-getopt no-DBus i18n IDN DHCP DHCPv6 Lua 
TFTP no-conntrack no-ipset auth
dnsmasq: using nameserver 127.0.0.1#53
dnsmasq: read /etc/hosts - 5 addresses

and

COMMAND  PID USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
named    889 bind   20u  IPv4 0xfffffe0005d823d0      0t0  TCP localhost:domain 
(LISTEN)
named    889 bind  512u  IPv4 0xfffffe0005b590c0      0t0  UDP localhost:domain
dnsmasq 4664 root    3u  IPv4 0xfffffe0005b59720      0t0  UDP *:domain
dnsmasq 4664 root    4u  IPv4 0xfffffe006f9f37a0      0t0  TCP *:domain (LISTEN)
dnsmasq 4664 root    5u  IPv6 0xfffffe0005b596f0      0t0  UDP *:domain
dnsmasq 4664 root    6u  IPv6 0xfffffe006fa6f7a0      0t0  TCP *:domain (LISTEN)

Do you need anything else to debug this?



Yes,

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?

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.


I'll commit a fix for the simple errno problem, to make things easier.


Cheers,

Simon.

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

Reply via email to