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.
>>> I thought about this and checked back through some earlier fixes, and
>>> found this.
>>> which refers to exactly the same situation you're working with, but in
>>> 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
> 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.
More information about the Dnsmasq-discuss