[Dnsmasq-discuss] SUCCESS

Gene Czarcinski gene at czarc.net
Wed Oct 17 14:54:56 BST 2012


On 10/17/2012 05:06 AM, Simon Kelley wrote:
> 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.
OK, I believe I understand: as you describe it, this is needed for 
dhcp4. However, getting a little more understanding of how dhcp6 works 
from my last round of debugging, dhcp6 currently does handle multiple 
packets.  It filters on the IPv6 subnet specified in --dhcp-range and 
will only serve dhcp6-packets coming in on the interface which has the 
defined dhcp-range subnet.  If you specify more than one subnet for a 
specific dnsmasq, then it will serve each. Any --interface or 
--listen-address is irrelevant.  However, the two exclude lists are not 
irrelevant and any interface specified in wither of those lists will 
block the service.

Now, I assume that all dhcmasq instantiations will each get copies of 
all dhcp6 packets.  It is their responsibility to process or drop a 
packet depending on just what they service.

Well, if a mistake is made and two dnsmasq processes are service the 
same IPv6 subnet ... unpredictable results will occur.
>
>>>
>>> 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.
I will be filing a bugzilla report and will specifically cite these 
messages from the archive.

Gene



More information about the Dnsmasq-discuss mailing list