Hi Martin, I think it would make more sense to not derive intended behaviour from number of interfaces but allow desired behaviour to be specified explicitly.
If machines want to reuse the same address multiple times on different interfaces, they may want explicit configuration of BINDTODEVICE enabled. Default configuration may stay auto detection to keep backward compatibility, but would allow configuring it without surprises. On the other hand, it seems to me binding just to single device is limitation of current code more that well thought requirement. More below. After experience with TCP socket on interfaces, I think it should log changes in listening sockets. It is nightmare to debug that in debugger. Regards, Petr On 7/5/19 12:55 PM, Martin Wilck wrote: > I've just found a strange issue with dnsmasq's dhcp server, which I > believe is caused by the commit 9380ba7 "Set SO_BINDTODEVICE on DHCP > sockets when doing DHCP on one interface". > > I was running a single instance dnsmasq for on various local interfaces > on my system. At the same time, I was running libvirt managed networks, > which spawn a separate dnsmasq instance for every network created. > (That's the way it has to be with libvirt). The configuration of the > first, multiple-interface instance was done with "listen-address" and > "bind-dynamic"; the listen addresses were 127.0.0.1 plus one address on > every VLAN on this server. > > Anyway, the above-mentioned commit causes strange behavior for the > multi-interface dnsmasq instance. SO_BINDTODEVICE will be used if and > only if exactly one of the configured interfaces is up when dnsmasq is > started. In this case, if other interfaces are brought up later, dhcp > queries via these new interfaces don't work, because the dhcp socket is > bound to the first interface only. If at the time of dnsmasq startup, > either 0 or >= 2 interfaces are up, dhcp queries work just fine from > any interface, including those brought up later. > > While this is certainly a corner case, it strongly violates the > principle of least surprise - the status at the time of dnsmasq startup > has an effect on whether freshly brought-up interfaces will be serviced > later. Especially with "bind-dynamic", my expectation was that > dynamically added interfaces would be served. They would be, but only for DNS queries. Handling of DHCP sockets is different, they always use SO_REUSEPORT. Only DHCP would bind to device. DNS code is intentionally binding just one time to single address. DHCP socket on contrary would bind to ANY address and bind it to device. It would require multiple sockets for DHCP on each interface it listens on. It has now just single socket globally, so listener would have to be moved from dhcp_init/make_fd to something reacting to newaddress. Like create_bound_listeners(0) for example? But where would be stored socket bound to each device? daemon->dhcpfd cannot be bound to multiple interfaces. I think possible solution would be to move socket itself into struct irec, to daemon->interfaces. There is parameter dhcp_ok, which is checked only in whichdevice. It is computed again on every enumerate_interfaces after each change. It only checks whether there is (dhcp) single device. Instead, it could create listener socket for each interface served and bind to it. I think current state is needed, because bigger rewrite was never done to dhcp sockets. Without it, it has to be just single socket. structure listener (used in dns and tftp) does not use SO_REUSEPORT, so there has to be just single listener on single address. DHCP socket needs the opposite, binding to every interface enabled separately. > > According to the bug report that motivated the mentioned patch ( > http://codeha.us/openstack/msg09684.html), such a mixture of multi- > interface and single-interface instances would be doomed to fail > anyway, because of the issues related to receiving DHCP unicast > packets. Thus perhaps this configuration should be generally forbidden > - but I, for one, have not observed the reported unicast-packet issues > (failing dhcp requests or renewals) up to now. > > Would it perhaps be possible to re-run the SO_BINDTODEVICE logic in the > newaddress() code path, and dynamically bind/undbind the socket if the > number of dhcp interfaces changed between 1 and something else? > > Regards, > Martin > > > > > _______________________________________________ > Dnsmasq-discuss mailing list > Dnsmasqfirstname.lastname@example.org > http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss > -- Petr Menšík Software Engineer Red Hat, http://www.redhat.com/ email: pemen...@redhat.com PGP: 65C6C973 _______________________________________________ Dnsmasq-discuss mailing list Dnsmasqemail@example.com http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss