summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Kelley <simon@thekelleys.org.uk>2012-02-29 20:10:31 +0000
committerSimon Kelley <simon@thekelleys.org.uk>2012-02-29 20:10:31 +0000
commit552af8b988ea80218c60a5b0fb5baccd1c2e1301 (patch)
tree530d0edfa7b9921c7e557b0382b6e6ea58fc9f9a
parent4f8ff361dc21b758ccdcd6545fd2bc0a4c43a820 (diff)
downloaddnsmasq-2.60rc2.tar.gz
Fix --localise-queries via interface lo bug.v2.60rc2
-rw-r--r--CHANGELOG5
-rw-r--r--src/forward.c33
2 files changed, 32 insertions, 6 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 3269406..b7c870e 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -71,6 +71,11 @@ version 2.60
configuration from the DHCPv6 conf, and should just need
enabling with --enable-ra.
+ Fix long-standing wrinkle with --localise-queries that
+ could result in wrong answers when DNS packets arrive
+ via an interface other than the expected one. Thanks to
+ Lorenzo Milesi and John Hanks for spotting this one.
+
version 2.59
Fix regression in 2.58 which caused failure to start up
diff --git a/src/forward.c b/src/forward.c
index af322da..e3bf7d7 100644
--- a/src/forward.c
+++ b/src/forward.c
@@ -766,12 +766,33 @@ void receive_query(struct listener *listen, time_t now)
!iface_check(listen->family, &dst_addr, ifr.ifr_name))
return;
- if (listen->family == AF_INET &&
- option_bool(OPT_LOCALISE) &&
- ioctl(listen->fd, SIOCGIFNETMASK, &ifr) == -1)
- return;
-
- netmask = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
+ if (listen->family == AF_INET && option_bool(OPT_LOCALISE))
+ {
+ struct irec *iface;
+
+ /* get the netmask of the interface whch has the address we were sent to.
+ This is no neccessarily the interface we arrived on. */
+
+ for (iface = daemon->interfaces; iface; iface = iface->next)
+ if (iface->addr.sa.sa_family == AF_INET &&
+ iface->addr.in.sin_addr.s_addr == dst_addr_4.s_addr)
+ break;
+
+ /* interface may be new */
+ if (!iface)
+ enumerate_interfaces();
+
+ for (iface = daemon->interfaces; iface; iface = iface->next)
+ if (iface->addr.sa.sa_family == AF_INET &&
+ iface->addr.in.sin_addr.s_addr == dst_addr_4.s_addr)
+ break;
+
+ /* If we failed, abandon localisation */
+ if (iface)
+ netmask = iface->netmask;
+ else
+ dst_addr_4.s_addr = 0;
+ }
}
if (extract_request(header, (size_t)n, daemon->namebuff, &type))