[Dnsmasq-discuss] SUCCESS

Simon Kelley simon at thekelleys.org.uk
Wed Oct 17 10:06:31 BST 2012


On 16/10/12 21:49, Gene Czarcinski wrote:
> On 10/16/2012 03:51 PM, Simon Kelley wrote:
>> OK. I committed a variation on your code, which makes --listen-address
>> work with DHCPv6. This was definitely bugged before, and is sensible
>> now. Thanks.
> I do not believe that it was either --listen-address or --interface.  I
> believe that the old code was incorrectly checking for them.  The
> important thing is the subnetwork defined the the --dhcp-range
> specification and which device has that subnetwork. The only good thing
> the iface_check() did was to test for one of the two exclude lists with
> the other being checked by dhcp6_packet() itself.
>
> I believe that this same situation ("problem") exists in dhcp_packet()
> but it has some slightly different code paths so it ends up working.
>
> As I was writing this, I thought of an interesting (possible problem)
> "feature".  I believe that with the new dhcp6 code, that you could have
> dhcp6 service without any --interface or --listen-address ... you just
> cannot have that interface on an exclude list.

That's correct, and by design. --interface and --listen-address are 
access controls, the default if they are not given is full access. Apart 
from anything else, that's backwards compatible with paleo versions of 
dnsmasq which didn't implement these.

Of course for DHCP, you need a suitable dhcp-range for the arrival 
interface, otherwise a DHCP request will just result in a "No DHCP range 
for request in <interface>" message.
>
>>
>>
>> BUT
>>
>> I thought about this and checked back through some earlier fixes, and
>> found this.
>>
>> https://bugs.launchpad.net/ubuntu/+source/dnsmasq/+bug/1013529
>>
>> which refers to exactly the same situation you're working with, but in
>> OpenStack.
>>
>> The important take-home is that to make DHCP work with multiple
>> instances of dnsmasq, each dealing with a single interface, it's
>> necessary to set SO_BINDTODEVICE on the DHCP socket to associate it
>> with a particular interface. The patch which went in around 2.61 -
>> 2.62 does just that, provided that there is exactly one --interface
>> parameter. It doesn't work with --listen-address.
>>
>> So, to make libvirt work correctly in all circumstances, it will need
>> to use --interface, and NOT --listen-address. This applies to DHCPv4
>> as well as DHCPv6.
> Now this I do not understand.  While libvirt does not currently support
> dhcp6, it does support dhcp4 and runs one copy of dnsmasq for each
> virtual network.  I am pasting in a typical command line as shown by "ps
> ax".  Yes, everything is on the command line.  One of these days, if I
> feel ambitious enough, I am going to change it to put everything into a
> conf file and maybe add a --con-dir so that you could test some stuff
> without standing on your head ... rebuilding the libvirt rpms takes a
> little time.
>
>
> ---- I broke the text up to multi line so it is readable
> --------------------------------
> /sbin/dnsmasq --strict-order --bind-interfaces --domain=virt
> --local=/virt/ \
> --domain-needed --pid-file=/var/run/libvirt/network/default.pid \
> --conf-file= --except-interface lo \
> --listen-address 192.168.122.1 --local=/122.168.192.in-addr.arpa/ \
> --dhcp-range 192.168.122.2,192.168.122.254 \
> --dhcp-leasefile=/var/lib/libvirt/dnsmasq/default.leases \
> --dhcp-lease-max=253 --dhcp-no-override --expand-hosts
> --------------------------------------------------------------------------------------------------
>
>
> Comments?

The problem is that when you have more than one instance of dnsmasq 
doing DHCP. Each instance is listening on *:67. Now, a packet arrives 
for port 67 on a particular interface. How is the kernel supposed know 
which instance of dnsmasq to send it to? It can't and sometimes gets it 
wrong. This is normally masked because DHCP clients fall back to 
broadcast, and they get sent to _all_ the listeners, (check the bug 
report I referenced) but there are situations were this fails.

For DNS, with --bind-interfaces, there isn't a problem, because when 
dnsmasq is configured with --interface or --listen-address then port 53 
is bound to a particular address, not the wildcard address. DHCP always 
binds the wildcard address (there are some strange packets in a DHCP 
exchange that get missed otherwise.) As we've seen, --interface or 
--listen-address is an access control mechanism in the DHCP code: 
recieve all packets and filter.

The change in 2.61 is that when dnsmasq is configured with exactly one 
--interface, it calls an obscure Linux-only socket option, 
SO_BINDTODEVICE on the DHCP socket (which is bound to *:67). That has 
the effect of getting the right packets to the right dnsmasq instance. 
It only works for exactly one --interface (otherwise, dnsmasq would have 
to start handling multiple DHCP sockets - a big change.)

The SO_BINDTODEVICE stuff only works with --interface, not 
--listen-address, hence the desirability of moving libvirt from 
--listen-address to --interface.

THis stuff is all horrible, a legacy of the LSD-inspired Berkeley 
sockets API. dnsmasq was originally intended to be run as one daemon on 
a machine, handling multiple interfaces. Adapting to the 
one-dnsmasq-per-interface paradigm has been a long hard road.

>>
>> Gene, I'm hoping you can act as the conduit for this information to
>> the libvirt community. It's a tough job, etc, etc.
> Tell me about it.
>

Anything I can do to help, let me know.


Cheers,

Simon.





More information about the Dnsmasq-discuss mailing list