mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-19 18:28:25 +00:00
Set SO_BINDTODEVICE on DHCP sockets when doing DHCP on one interface
only. Fixes OpenSTack use-case.
This commit is contained in:
@@ -81,6 +81,13 @@ version 2.61
|
|||||||
may erroneously look like a valid CNAME to a non-exitant
|
may erroneously look like a valid CNAME to a non-exitant
|
||||||
name. Thanks to Ben Winslow for finding this.
|
name. Thanks to Ben Winslow for finding this.
|
||||||
|
|
||||||
|
Call SO_BINDTODEVICE on the DHCP socket(s) when doing DHCP
|
||||||
|
on exacly one interface and --bind-interfaces is set. This
|
||||||
|
makes the OpenStack use-case of one dnsmasq per virtual
|
||||||
|
interface work. This is only available on Linux; it's not
|
||||||
|
supported on other platforms. Thanks to Vishvananda Ishaya
|
||||||
|
and thr OpenStack team for the suggestion.
|
||||||
|
|
||||||
|
|
||||||
version 2.60
|
version 2.60
|
||||||
Fix compilation problem in Mac OS X Lion. Thanks to Olaf
|
Fix compilation problem in Mac OS X Lion. Thanks to Olaf
|
||||||
|
|||||||
@@ -451,6 +451,41 @@ void join_multicast(void)
|
|||||||
}
|
}
|
||||||
#endif
|
#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 {
|
static const struct opttab_t {
|
||||||
char *name;
|
char *name;
|
||||||
|
|||||||
@@ -209,6 +209,21 @@ int main (int argc, char **argv)
|
|||||||
for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
|
for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
|
||||||
if (if_tmp->name && !if_tmp->used)
|
if (if_tmp->name && !if_tmp->used)
|
||||||
die(_("unknown interface %s"), if_tmp->name, EC_BADNET);
|
die(_("unknown interface %s"), if_tmp->name, EC_BADNET);
|
||||||
|
|
||||||
|
#if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP)
|
||||||
|
/* after enumerate_interfaces() */
|
||||||
|
if (daemon->dhcp)
|
||||||
|
{
|
||||||
|
bindtodevice(daemon->dhcpfd);
|
||||||
|
if (daemon->enable_pxe)
|
||||||
|
bindtodevice(daemon->pxefd);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP6)
|
||||||
|
if (daemon->dhcp6)
|
||||||
|
bindtodevice(daemon->dhcp6fd);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
create_wildcard_listeners();
|
create_wildcard_listeners();
|
||||||
|
|||||||
@@ -388,7 +388,7 @@ struct server {
|
|||||||
struct irec {
|
struct irec {
|
||||||
union mysockaddr addr;
|
union mysockaddr addr;
|
||||||
struct in_addr netmask; /* only valid for IPv4 */
|
struct in_addr netmask; /* only valid for IPv4 */
|
||||||
int tftp_ok, mtu, done, dad;
|
int tftp_ok, dhcp_ok, mtu, done, dad;
|
||||||
char *name;
|
char *name;
|
||||||
struct irec *next;
|
struct irec *next;
|
||||||
};
|
};
|
||||||
@@ -1108,6 +1108,9 @@ u16 lookup_dhcp_opt(int prot, char *name);
|
|||||||
u16 lookup_dhcp_len(int prot, u16 val);
|
u16 lookup_dhcp_len(int prot, u16 val);
|
||||||
char *option_string(int prot, unsigned int opt, unsigned char *val,
|
char *option_string(int prot, unsigned int opt, unsigned char *val,
|
||||||
int opt_len, char *buf, int buf_len);
|
int opt_len, char *buf, int buf_len);
|
||||||
|
#ifdef HAVE_LINUX_NETWORK
|
||||||
|
void bindtodevice(int fd);
|
||||||
|
#endif
|
||||||
# ifdef HAVE_DHCP6
|
# ifdef HAVE_DHCP6
|
||||||
void display_opts6(void);
|
void display_opts6(void);
|
||||||
void join_multicast(void);
|
void join_multicast(void);
|
||||||
|
|||||||
@@ -162,6 +162,7 @@ static int iface_allowed(struct irec **irecp, int if_index,
|
|||||||
int fd, mtu = 0, loopback;
|
int fd, mtu = 0, loopback;
|
||||||
struct ifreq ifr;
|
struct ifreq ifr;
|
||||||
int tftp_ok = daemon->tftp_unlimited;
|
int tftp_ok = daemon->tftp_unlimited;
|
||||||
|
int dhcp_ok = 1;
|
||||||
#ifdef HAVE_DHCP
|
#ifdef HAVE_DHCP
|
||||||
struct iname *tmp;
|
struct iname *tmp;
|
||||||
#endif
|
#endif
|
||||||
@@ -191,6 +192,9 @@ static int iface_allowed(struct irec **irecp, int if_index,
|
|||||||
|
|
||||||
loopback = ifr.ifr_flags & IFF_LOOPBACK;
|
loopback = ifr.ifr_flags & IFF_LOOPBACK;
|
||||||
|
|
||||||
|
if (loopback)
|
||||||
|
dhcp_ok = 0;
|
||||||
|
|
||||||
if (ioctl(fd, SIOCGIFMTU, &ifr) != -1)
|
if (ioctl(fd, SIOCGIFMTU, &ifr) != -1)
|
||||||
mtu = ifr.ifr_mtu;
|
mtu = ifr.ifr_mtu;
|
||||||
|
|
||||||
@@ -238,7 +242,10 @@ static int iface_allowed(struct irec **irecp, int if_index,
|
|||||||
#ifdef HAVE_DHCP
|
#ifdef HAVE_DHCP
|
||||||
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
|
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
|
||||||
if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
|
if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
|
||||||
|
{
|
||||||
tftp_ok = 0;
|
tftp_ok = 0;
|
||||||
|
dhcp_ok = 0;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
@@ -254,6 +261,7 @@ static int iface_allowed(struct irec **irecp, int if_index,
|
|||||||
iface->addr = *addr;
|
iface->addr = *addr;
|
||||||
iface->netmask = netmask;
|
iface->netmask = netmask;
|
||||||
iface->tftp_ok = tftp_ok;
|
iface->tftp_ok = tftp_ok;
|
||||||
|
iface->dhcp_ok = dhcp_ok;
|
||||||
iface->mtu = mtu;
|
iface->mtu = mtu;
|
||||||
iface->dad = dad;
|
iface->dad = dad;
|
||||||
iface->done = 0;
|
iface->done = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user