diff options
-rw-r--r-- | CHANGELOG | 5 | ||||
-rw-r--r-- | src/forward.c | 33 |
2 files changed, 32 insertions, 6 deletions
@@ -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)) |