mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-19 18:28:25 +00:00
Make --listen-address work for all 127.0.0.0/8 addresses.
This commit is contained in:
11
CHANGELOG
11
CHANGELOG
@@ -40,7 +40,16 @@ version 2.61
|
||||
|
||||
Set the environment variable DNSMASQ_LOG_DHCP when running
|
||||
the script id --log-dhcp is in effect, so that script can
|
||||
taylor their logging verbosity. Suggestion from Malte Forkel.
|
||||
taylor their logging verbosity. Suggestion from Malte
|
||||
Forkel.
|
||||
|
||||
Arrange that addresses specified with --listen-address
|
||||
work even if there is no interface carrying the
|
||||
address. This is chiefly useful for IPv4 loopback
|
||||
addresses, where any address in 127.0.0.0/8 is a valid
|
||||
loopback address, but normally only 127.0.0.1 appears on
|
||||
the lo interface. Thanks to Mathieu Trudel-Lapierre for
|
||||
the idea and initial patch.
|
||||
|
||||
|
||||
version 2.60
|
||||
|
||||
@@ -209,13 +209,6 @@ int main (int argc, char **argv)
|
||||
for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
|
||||
if (if_tmp->name && !if_tmp->used)
|
||||
die(_("unknown interface %s"), if_tmp->name, EC_BADNET);
|
||||
|
||||
for (if_tmp = daemon->if_addrs; if_tmp; if_tmp = if_tmp->next)
|
||||
if (!if_tmp->used)
|
||||
{
|
||||
prettyprint_addr(&if_tmp->addr, daemon->namebuff);
|
||||
die(_("no interface with address %s"), daemon->namebuff, EC_BADNET);
|
||||
}
|
||||
}
|
||||
else
|
||||
create_wildcard_listeners();
|
||||
@@ -1284,18 +1277,19 @@ static void check_dns_listeners(fd_set *set, time_t now)
|
||||
int confd;
|
||||
struct irec *iface = NULL;
|
||||
pid_t p;
|
||||
union mysockaddr tcp_addr;
|
||||
socklen_t tcp_len = sizeof(union mysockaddr);
|
||||
|
||||
while ((confd = accept(listener->tcpfd, NULL, NULL)) == -1 && errno == EINTR);
|
||||
|
||||
while((confd = accept(listener->tcpfd, NULL, NULL)) == -1 && errno == EINTR);
|
||||
|
||||
if (confd == -1)
|
||||
if (confd == -1 ||
|
||||
getsockname(confd, (struct sockaddr *)&tcp_addr, &tcp_len) == -1)
|
||||
continue;
|
||||
|
||||
if (option_bool(OPT_NOWILD))
|
||||
iface = listener->iface;
|
||||
iface = listener->iface; /* May be NULL */
|
||||
else
|
||||
{
|
||||
union mysockaddr tcp_addr;
|
||||
socklen_t tcp_len = sizeof(union mysockaddr);
|
||||
/* Check for allowed interfaces when binding the wildcard address:
|
||||
we do this by looking for an interface with the same address as
|
||||
the local address of the TCP connection, then looking to see if that's
|
||||
@@ -1303,14 +1297,13 @@ static void check_dns_listeners(fd_set *set, time_t now)
|
||||
interface too, for localisation. */
|
||||
|
||||
/* interface may be new since startup */
|
||||
if (enumerate_interfaces() &&
|
||||
getsockname(confd, (struct sockaddr *)&tcp_addr, &tcp_len) != -1)
|
||||
if (enumerate_interfaces())
|
||||
for (iface = daemon->interfaces; iface; iface = iface->next)
|
||||
if (sockaddr_isequal(&iface->addr, &tcp_addr))
|
||||
break;
|
||||
}
|
||||
|
||||
if (!iface)
|
||||
if (!iface && !option_bool(OPT_NOWILD))
|
||||
{
|
||||
shutdown(confd, SHUT_RDWR);
|
||||
close(confd);
|
||||
@@ -1336,7 +1329,13 @@ static void check_dns_listeners(fd_set *set, time_t now)
|
||||
unsigned char *buff;
|
||||
struct server *s;
|
||||
int flags;
|
||||
|
||||
struct in_addr netmask;
|
||||
|
||||
if (iface)
|
||||
netmask = iface->netmask;
|
||||
else
|
||||
netmask.s_addr = 0;
|
||||
|
||||
#ifndef NO_FORK
|
||||
/* Arrange for SIGALARM after CHILD_LIFETIME seconds to
|
||||
terminate the process. */
|
||||
@@ -1354,7 +1353,7 @@ static void check_dns_listeners(fd_set *set, time_t now)
|
||||
if ((flags = fcntl(confd, F_GETFL, 0)) != -1)
|
||||
fcntl(confd, F_SETFL, flags & ~O_NONBLOCK);
|
||||
|
||||
buff = tcp_request(confd, now, &iface->addr, iface->netmask);
|
||||
buff = tcp_request(confd, now, &tcp_addr, netmask);
|
||||
|
||||
shutdown(confd, SHUT_RDWR);
|
||||
close(confd);
|
||||
|
||||
@@ -395,7 +395,7 @@ struct irec {
|
||||
|
||||
struct listener {
|
||||
int fd, tcpfd, tftpfd, family;
|
||||
struct irec *iface; /* only valid for non-wildcard */
|
||||
struct irec *iface; /* only sometimes valid for non-wildcard */
|
||||
struct listener *next;
|
||||
};
|
||||
|
||||
|
||||
@@ -660,7 +660,7 @@ void receive_query(struct listener *listen, time_t now)
|
||||
/* packet buffer overwritten */
|
||||
daemon->srv_save = NULL;
|
||||
|
||||
if (listen->family == AF_INET && option_bool(OPT_NOWILD))
|
||||
if (listen->iface && listen->family == AF_INET && option_bool(OPT_NOWILD))
|
||||
{
|
||||
dst_addr_4 = listen->iface->addr.in.sin_addr;
|
||||
netmask = listen->iface->netmask;
|
||||
|
||||
@@ -511,6 +511,7 @@ void create_bound_listeners(int dienow)
|
||||
{
|
||||
struct listener *new;
|
||||
struct irec *iface;
|
||||
struct iname *if_tmp;
|
||||
|
||||
for (iface = daemon->interfaces; iface; iface = iface->next)
|
||||
if (!iface->done && !iface->dad &&
|
||||
@@ -521,6 +522,25 @@ void create_bound_listeners(int dienow)
|
||||
daemon->listeners = new;
|
||||
iface->done = 1;
|
||||
}
|
||||
|
||||
/* Check for --listen-address options that haven't been used because there's
|
||||
no interface with a matching address. These may be valid: eg it's possible
|
||||
to listen on 127.0.1.1 even if the loopback interface is 127.0.0.1
|
||||
|
||||
If the address isn't valid the bind() will fail and we'll die().
|
||||
|
||||
The resulting listeners have the ->iface field NULL, and this has to be
|
||||
handled by the DNS and TFTP code. It disables --localise-queries processing
|
||||
(no netmask) and some MTU login the tftp code. */
|
||||
|
||||
for (if_tmp = daemon->if_addrs; if_tmp; if_tmp = if_tmp->next)
|
||||
if (!if_tmp->used &&
|
||||
(new = create_listeners(&if_tmp->addr, 1, dienow)))
|
||||
{
|
||||
new->iface = NULL;
|
||||
new->next = daemon->listeners;
|
||||
daemon->listeners = new;
|
||||
}
|
||||
}
|
||||
|
||||
int is_dad_listeners(void)
|
||||
|
||||
40
src/tftp.c
40
src/tftp.c
@@ -57,7 +57,7 @@ void tftp_request(struct listener *listen, time_t now)
|
||||
int mtuflag = IP_PMTUDISC_DONT;
|
||||
#endif
|
||||
char namebuff[IF_NAMESIZE];
|
||||
char *name;
|
||||
char *name = NULL;
|
||||
char *prefix = daemon->tftp_prefix;
|
||||
struct tftp_prefix *pref;
|
||||
struct interface_list *ir;
|
||||
@@ -95,9 +95,20 @@ void tftp_request(struct listener *listen, time_t now)
|
||||
|
||||
if (option_bool(OPT_NOWILD))
|
||||
{
|
||||
addr = listen->iface->addr;
|
||||
mtu = listen->iface->mtu;
|
||||
name = listen->iface->name;
|
||||
if (listen->iface)
|
||||
{
|
||||
addr = listen->iface->addr;
|
||||
mtu = listen->iface->mtu;
|
||||
name = listen->iface->name;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* we're listening on an address that doesn't appear on an interface,
|
||||
ask the kernel what the socket is bound to */
|
||||
socklen_t tcp_len = sizeof(union mysockaddr);
|
||||
if (getsockname(listen->tftpfd, (struct sockaddr *)&addr, &tcp_len) == -1)
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -211,15 +222,18 @@ void tftp_request(struct listener *listen, time_t now)
|
||||
mtu = ifr.ifr_mtu;
|
||||
}
|
||||
|
||||
/* check for per-interface prefix */
|
||||
for (pref = daemon->if_prefix; pref; pref = pref->next)
|
||||
if (strcmp(pref->interface, name) == 0)
|
||||
prefix = pref->prefix;
|
||||
|
||||
/* wierd TFTP interfaces disable special options. */
|
||||
for (ir = daemon->tftp_interfaces; ir; ir = ir->next)
|
||||
if (strcmp(ir->interface, name) == 0)
|
||||
special = 1;
|
||||
if (name)
|
||||
{
|
||||
/* check for per-interface prefix */
|
||||
for (pref = daemon->if_prefix; pref; pref = pref->next)
|
||||
if (strcmp(pref->interface, name) == 0)
|
||||
prefix = pref->prefix;
|
||||
|
||||
/* wierd TFTP interfaces disable special options. */
|
||||
for (ir = daemon->tftp_interfaces; ir; ir = ir->next)
|
||||
if (strcmp(ir->interface, name) == 0)
|
||||
special = 1;
|
||||
}
|
||||
|
||||
if (listen->family == AF_INET)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user