Commit 45cca585 authored by Simon Kelley's avatar Simon Kelley

Fix caching of dangling CNAMEs.

parent e136725c
...@@ -149,6 +149,9 @@ version 2.67 ...@@ -149,6 +149,9 @@ version 2.67
no address, and vice-versa. Thanks to Yury Konovalov for no address, and vice-versa. Thanks to Yury Konovalov for
spotting the problem. spotting the problem.
Do a better job caching dangling CNAMEs. Thanks to Yves
Dorfsman for spotting the problem.
version 2.66 version 2.66
Add the ability to act as an authoritative DNS Add the ability to act as an authoritative DNS
......
...@@ -1011,91 +1011,88 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t ...@@ -1011,91 +1011,88 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
else else
continue; continue;
if (!(flags & F_NXDOMAIN)) cname_loop1:
if (!(p1 = skip_questions(header, qlen)))
return 0;
for (j = ntohs(header->ancount); j != 0; j--)
{ {
cname_loop1: if (!(res = extract_name(header, qlen, &p1, name, 0, 10)))
if (!(p1 = skip_questions(header, qlen))) return 0; /* bad packet */
return 0;
for (j = ntohs(header->ancount); j != 0; j--) GETSHORT(aqtype, p1);
GETSHORT(aqclass, p1);
GETLONG(attl, p1);
if ((daemon->max_ttl != 0) && (attl > daemon->max_ttl) && !is_sign)
{ {
if (!(res = extract_name(header, qlen, &p1, name, 0, 10))) (p1) -= 4;
return 0; /* bad packet */ PUTLONG(daemon->max_ttl, p1);
}
GETSHORT(aqtype, p1); GETSHORT(ardlen, p1);
GETSHORT(aqclass, p1); endrr = p1+ardlen;
GETLONG(attl, p1);
if ((daemon->max_ttl != 0) && (attl > daemon->max_ttl) && !is_sign) if (aqclass == C_IN && res != 2 && (aqtype == T_CNAME || aqtype == qtype))
{ {
(p1) -= 4; if (aqtype == T_CNAME)
PUTLONG(daemon->max_ttl, p1);
}
GETSHORT(ardlen, p1);
endrr = p1+ardlen;
if (aqclass == C_IN && res != 2 && (aqtype == T_CNAME || aqtype == qtype))
{ {
if (aqtype == T_CNAME) if (!cname_count--)
return 0; /* looped CNAMES */
newc = cache_insert(name, NULL, now, attl, F_CNAME | F_FORWARD);
if (newc)
{ {
if (!cname_count--) newc->addr.cname.target.cache = NULL;
return 0; /* looped CNAMES */ if (cpp)
newc = cache_insert(name, NULL, now, attl, F_CNAME | F_FORWARD);
if (newc)
{ {
newc->addr.cname.target.cache = NULL; cpp->addr.cname.target.cache = newc;
if (cpp) cpp->addr.cname.uid = newc->uid;
{
cpp->addr.cname.target.cache = newc;
cpp->addr.cname.uid = newc->uid;
}
} }
cpp = newc;
if (attl < cttl)
cttl = attl;
if (!extract_name(header, qlen, &p1, name, 1, 0))
return 0;
goto cname_loop1;
} }
else
{ cpp = newc;
found = 1; if (attl < cttl)
cttl = attl;
/* copy address into aligned storage */
if (!CHECK_LEN(header, p1, qlen, addrlen)) if (!extract_name(header, qlen, &p1, name, 1, 0))
return 0; /* bad packet */ return 0;
memcpy(&addr, p1, addrlen); goto cname_loop1;
}
/* check for returned address in private space */ else if (!(flags & F_NXDOMAIN))
if (check_rebind && {
(flags & F_IPV4) && found = 1;
private_net(addr.addr.addr4, !option_bool(OPT_LOCAL_REBIND)))
return 1; /* copy address into aligned storage */
if (!CHECK_LEN(header, p1, qlen, addrlen))
return 0; /* bad packet */
memcpy(&addr, p1, addrlen);
/* check for returned address in private space */
if (check_rebind &&
(flags & F_IPV4) &&
private_net(addr.addr.addr4, !option_bool(OPT_LOCAL_REBIND)))
return 1;
#ifdef HAVE_IPSET #ifdef HAVE_IPSET
if (ipsets && (flags & (F_IPV4 | F_IPV6))) if (ipsets && (flags & (F_IPV4 | F_IPV6)))
{ {
ipsets_cur = ipsets; ipsets_cur = ipsets;
while (*ipsets_cur) while (*ipsets_cur)
add_to_ipset(*ipsets_cur++, &addr, flags, 0); add_to_ipset(*ipsets_cur++, &addr, flags, 0);
} }
#endif #endif
newc = cache_insert(name, &addr, now, attl, flags | F_FORWARD); newc = cache_insert(name, &addr, now, attl, flags | F_FORWARD);
if (newc && cpp) if (newc && cpp)
{ {
cpp->addr.cname.target.cache = newc; cpp->addr.cname.target.cache = newc;
cpp->addr.cname.uid = newc->uid; cpp->addr.cname.uid = newc->uid;
}
cpp = NULL;
} }
cpp = NULL;
} }
p1 = endrr;
if (!CHECK_LEN(header, p1, qlen, 0))
return 0; /* bad packet */
} }
p1 = endrr;
if (!CHECK_LEN(header, p1, qlen, 0))
return 0; /* bad packet */
} }
if (!found && !option_bool(OPT_NO_NEG)) if (!found && !option_bool(OPT_NO_NEG))
...@@ -2035,7 +2032,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, ...@@ -2035,7 +2032,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
if (trunc) if (trunc)
header->hb3 |= HB3_TC; header->hb3 |= HB3_TC;
if (anscount == 0 && nxdomain) if (nxdomain)
SET_RCODE(header, NXDOMAIN); SET_RCODE(header, NXDOMAIN);
else else
SET_RCODE(header, NOERROR); /* no error */ SET_RCODE(header, NOERROR); /* no error */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment