Set SO_BINDTODEVICE on DHCP sockets when doing DHCP on one interface
only. Fixes OpenSTack use-case.
diff --git a/src/dhcp-common.c b/src/dhcp-common.c
index f19a33e..9d1290c 100644
--- a/src/dhcp-common.c
+++ b/src/dhcp-common.c
@@ -451,6 +451,41 @@
}
#endif
+#ifdef HAVE_LINUX_NETWORK
+void bindtodevice(int fd)
+{
+ /* If we are doing DHCP on exactly one interface, and running linux, do SO_BINDTODEVICE
+ to that device. This is for the use case of (eg) OpenStack, which runs a new
+ dnsmasq instance for each VLAN interface it creates. Without the BINDTODEVICE,
+ individual processes don't always see the packets they should.
+ SO_BINDTODEVICE is only available Linux. */
+
+ struct irec *iface, *found;
+
+ for (found = NULL, iface = daemon->interfaces; iface; iface = iface->next)
+ if (iface->dhcp_ok)
+ {
+ if (!found)
+ found = iface;
+ else if (strcmp(found->name, iface->name) != 0)
+ {
+ /* more than one. */
+ found = NULL;
+ break;
+ }
+ }
+
+ if (found)
+ {
+ struct ifreq ifr;
+ strcpy(ifr.ifr_name, found->name);
+ /* only allowed by root. */
+ if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) == -1 &&
+ errno != EPERM)
+ die(_("failed to set SO_BINDTODEVICE on DHCP socket: %s"), NULL, EC_BADNET);
+ }
+}
+#endif
static const struct opttab_t {
char *name;