summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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))