Compare commits

...
7 Commits
Author SHA1 Message Date
Simon Kelley 0f437b3b5e Banish compiler warnings. 2024-12-20 21:57:21 +00:00
Simon Kelley 8a5fe8ce6b Extend the code to effciently close unwanted file descriptors to *BSD. 2024-12-20 21:51:24 +00:00
Matthias Andree 2a664c03db bpf.c: Follow callback updates. 2024-12-20 21:07:09 +00:00
Simon Kelley 4902807879 Fix [-Wgnu-variable-sized-type-not-at-end] warning.
Thanks to Matthias Andree for pointing out this one.
2024-12-20 21:05:13 +00:00
Simon Kelley 742af6e4b9 Refactor receive_query() to removed duplicated code. 2024-12-20 20:02:01 +00:00
Simon Kelley 3eb008c36d Further refactoring of the TCP DNS codepath.
It's not t a thing of beauty, but it's less ugly than it was.
Any bugs, I blame on what I started from....
2024-12-19 16:38:47 +00:00
Simon Kelley 32248ebd5b Fix thinko in 3b74df4f55 2024-12-19 12:33:54 +00:00
4 changed files with 129 additions and 152 deletions

No files matched your search

+2 -2
View File
@@ -100,14 +100,14 @@ int arp_enumerate(void *parm, callback_t callback)
#endif /* defined(HAVE_BSD_NETWORK) && !defined(__APPLE__) */ #endif /* defined(HAVE_BSD_NETWORK) && !defined(__APPLE__) */
int iface_enumerate(int family, void *parm, int (*callback)()) int iface_enumerate(int family, void *parm, callback_t callback)
{ {
struct ifaddrs *head, *addrs; struct ifaddrs *head, *addrs;
int errsave, fd = -1, ret = 0; int errsave, fd = -1, ret = 0;
if (family == AF_UNSPEC) if (family == AF_UNSPEC)
#if defined(HAVE_BSD_NETWORK) && !defined(__APPLE__) #if defined(HAVE_BSD_NETWORK) && !defined(__APPLE__)
return arp_enumerate(parm, callback.af_unspec); return arp_enumerate(parm, callback);
#else #else
return 0; /* need code for Solaris and MacOS*/ return 0; /* need code for Solaris and MacOS*/
#endif #endif
+4 -1
View File
@@ -1125,7 +1125,10 @@ struct tftp_prefix {
}; };
struct dhcp_relay { struct dhcp_relay {
union all_addr local, server; union {
struct in_addr addr4;
struct in6_addr addr6;
} local, server;
char *interface; /* Allowable interface for replies from server, and dest for IPv6 multicast */ char *interface; /* Allowable interface for replies from server, and dest for IPv6 multicast */
int iface_index; /* working - interface in which requests arrived, for return */ int iface_index; /* working - interface in which requests arrived, for return */
int port; /* Port of relay we forward to. */ int port; /* Port of relay we forward to. */
+107 -147
View File
@@ -1227,15 +1227,19 @@ void reply_query(int fd, time_t now)
#ifdef HAVE_DNSSEC #ifdef HAVE_DNSSEC
if (option_bool(OPT_DNSSEC_VALID)) if (option_bool(OPT_DNSSEC_VALID))
{ {
/* Clear this in case we don't call dnssec_validate() below */ if ((forward->sentto->flags & SERV_DO_DNSSEC) && !(forward->flags & FREC_CHECKING_DISABLED))
memset(daemon->rr_status, 0, sizeof(*daemon->rr_status) * daemon->rr_status_sz); {
if ((forward->sentto->flags & SERV_DO_DNSSEC) &&
!(forward->flags & FREC_CHECKING_DISABLED))
dnssec_validate(forward, header, n, STAT_OK, now); dnssec_validate(forward, header, n, STAT_OK, now);
return;
}
/* If dnssec_validate() not called, rr_status{} is not valid
Clear it so we don't erroneously mark RRs as secure using stale data from
previous queries. */
memset(daemon->rr_status, 0, sizeof(*daemon->rr_status) * daemon->rr_status_sz);
} }
else
#endif #endif
return_reply(now, forward, header, n, STAT_OK); return_reply(now, forward, header, n, STAT_OK);
} }
@@ -1451,10 +1455,16 @@ void receive_query(struct listener *listen, time_t now)
size_t m; size_t m;
ssize_t n; ssize_t n;
int if_index = 0, auth_dns = 0, do_bit = 0, have_pseudoheader = 0; int if_index = 0, auth_dns = 0, do_bit = 0, have_pseudoheader = 0;
int stale = 0, filtered = 0, ede = EDE_UNSET, do_forward = 0;
int metric, ad_reqd, fd;
struct blockdata *saved_question = NULL;
#ifdef HAVE_CONNTRACK #ifdef HAVE_CONNTRACK
unsigned int mark = 0; unsigned int mark = 0;
int have_mark = 0; int have_mark = 0;
int is_single_query = 0, allowed = 1; int allowed = 1;
# ifdef HAVE_UBUS
int report = 0;
# endif
#endif #endif
#ifdef HAVE_AUTH #ifdef HAVE_AUTH
int local_auth = 0; int local_auth = 0;
@@ -1701,10 +1711,6 @@ void receive_query(struct listener *listen, time_t now)
log_query_mysockaddr(F_QUERY | F_FORWARD, daemon->namebuff, log_query_mysockaddr(F_QUERY | F_FORWARD, daemon->namebuff,
&source_addr, auth_dns ? "auth" : "query", type); &source_addr, auth_dns ? "auth" : "query", type);
#ifdef HAVE_CONNTRACK
is_single_query = 1;
#endif
#ifdef HAVE_AUTH #ifdef HAVE_AUTH
/* find queries for zones we're authoritative for, and answer them directly */ /* find queries for zones we're authoritative for, and answer them directly */
if (!auth_dns && !option_bool(OPT_LOCALISE)) if (!auth_dns && !option_bool(OPT_LOCALISE))
@@ -1746,86 +1752,70 @@ void receive_query(struct listener *listen, time_t now)
udp_size = PACKETSZ; /* Sanity check - can't reduce below default. RFC 6891 6.2.3 */ udp_size = PACKETSZ; /* Sanity check - can't reduce below default. RFC 6891 6.2.3 */
} }
ad_reqd = do_bit;
/* RFC 6840 5.7 */
if (header->hb4 & HB4_AD)
ad_reqd = 1;
fd = listen->fd;
#ifdef HAVE_CONNTRACK #ifdef HAVE_CONNTRACK
#ifdef HAVE_AUTH #ifdef HAVE_AUTH
if (!auth_dns || local_auth) if (!auth_dns || local_auth)
#endif #endif
if (option_bool(OPT_CMARK_ALST_EN) && have_mark && ((u32)mark & daemon->allowlist_mask)) if (option_bool(OPT_CMARK_ALST_EN) && have_mark && ((u32)mark & daemon->allowlist_mask))
allowed = is_query_allowed_for_mark((u32)mark, is_single_query ? daemon->namebuff : NULL); allowed = is_query_allowed_for_mark((u32)mark, daemon->namebuff);
#endif #endif
if (0); if (0);
#ifdef HAVE_CONNTRACK #ifdef HAVE_CONNTRACK
else if (!allowed) else if (!allowed)
{ {
u16 swap = htons(EDE_BLOCKED); ede = EDE_BLOCKED;
m = answer_disallowed(header, (size_t)n, (u32)mark, daemon->namebuff);
m = answer_disallowed(header, (size_t)n, (u32)mark, is_single_query ? daemon->namebuff : NULL); metric = METRIC_DNS_LOCAL_ANSWERED;
if (have_pseudoheader && m != 0)
m = add_pseudoheader(header, m, ((unsigned char *) header) + daemon->edns_pktsz,
EDNS0_OPTION_EDE, (unsigned char *)&swap, 2, do_bit, 0);
if (m >= 1)
{
#ifdef HAVE_DUMPFILE
dump_packet_udp(DUMP_REPLY, daemon->packet, m, NULL, &source_addr, listen->fd);
#endif
send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND),
(char *)header, m, &source_addr, &dst_addr, if_index);
daemon->metrics[METRIC_DNS_LOCAL_ANSWERED]++;
}
} }
#endif #endif
#ifdef HAVE_AUTH #ifdef HAVE_AUTH
else if (auth_dns) else if (auth_dns)
{ {
m = answer_auth(header, ((char *) header) + udp_size, (size_t)n, now, &source_addr, local_auth); m = answer_auth(header, ((char *) header) + udp_size, (size_t)n, now, &source_addr, local_auth);
if (m >= 1) metric = METRIC_DNS_AUTH_ANSWERED;
{
if (have_pseudoheader)
m = add_pseudoheader(header, m, ((unsigned char *) header) + udp_size,
0, NULL, 0, do_bit, 0);
#ifdef HAVE_DUMPFILE
dump_packet_udp(DUMP_REPLY, daemon->packet, m, NULL, &source_addr, listen->fd);
#endif
#if defined(HAVE_CONNTRACK) && defined(HAVE_UBUS) #if defined(HAVE_CONNTRACK) && defined(HAVE_UBUS)
if (local_auth) if (local_auth)
if (option_bool(OPT_CMARK_ALST_EN) && have_mark && ((u32)mark & daemon->allowlist_mask)) report = 1;
report_addresses(header, m, mark);
#endif #endif
send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND),
(char *)header, m, &source_addr, &dst_addr, if_index);
daemon->metrics[METRIC_DNS_AUTH_ANSWERED]++;
}
} }
#endif #endif
else else
{ {
int stale, filtered; saved_question = blockdata_alloc((char *) header, (size_t)n);
int ad_reqd = do_bit;
int fd = listen->fd;
struct blockdata *saved_question = blockdata_alloc((char *) header, (size_t)n);
/* RFC 6840 5.7 */
if (header->hb4 & HB4_AD)
ad_reqd = 1;
m = answer_request(header, ((char *) header) + udp_size, (size_t)n, m = answer_request(header, ((char *) header) + udp_size, (size_t)n,
dst_addr_4, netmask, now, ad_reqd, do_bit, &stale, &filtered); dst_addr_4, netmask, now, ad_reqd, do_bit, &stale, &filtered);
if (m >= 1) metric = stale ? METRIC_DNS_STALE_ANSWERED : METRIC_DNS_LOCAL_ANSWERED;
if (m == 0)
do_forward = 1;
else
{ {
if (have_pseudoheader) #if defined(HAVE_CONNTRACK) && defined(HAVE_UBUS)
{ report = 1;
int ede = EDE_UNSET; #endif
if (filtered) if (filtered)
ede = EDE_FILTERED; ede = EDE_FILTERED;
else if (stale) else if (stale)
ede = EDE_STALE; ede = EDE_STALE;
}
}
if (m != 0)
{
if (have_pseudoheader)
{
if (ede != EDE_UNSET) if (ede != EDE_UNSET)
{ {
u16 swap = htons(ede); u16 swap = htons(ede);
@@ -1841,22 +1831,22 @@ void receive_query(struct listener *listen, time_t now)
#ifdef HAVE_DUMPFILE #ifdef HAVE_DUMPFILE
dump_packet_udp(DUMP_REPLY, daemon->packet, m, NULL, &source_addr, listen->fd); dump_packet_udp(DUMP_REPLY, daemon->packet, m, NULL, &source_addr, listen->fd);
#endif #endif
#if defined(HAVE_CONNTRACK) && defined(HAVE_UBUS) #if defined(HAVE_CONNTRACK) && defined(HAVE_UBUS)
if (option_bool(OPT_CMARK_ALST_EN) && have_mark && ((u32)mark & daemon->allowlist_mask)) if (report)
report_addresses(header, m, mark); report_addresses(header, m, mark);
#endif #endif
send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND), send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND),
(char *)header, m, &source_addr, &dst_addr, if_index); (char *)header, m, &source_addr, &dst_addr, if_index);
daemon->metrics[METRIC_DNS_LOCAL_ANSWERED]++;
if (stale) daemon->metrics[metric]++;
daemon->metrics[METRIC_DNS_STALE_ANSWERED]++;
}
if (stale) if (stale)
{ {
/* We answered with stale cache data, so forward the query anyway to /* We answered with stale cache data, so forward the query anyway to
refresh that. */ refresh that. */
m = 0; do_forward = 1;
/* Don't mark the query with the source in this case. */ /* Don't mark the query with the source in this case. */
daemon->log_source_addr = NULL; daemon->log_source_addr = NULL;
@@ -1865,26 +1855,26 @@ void receive_query(struct listener *listen, time_t now)
when it comes back. */ when it comes back. */
fd = -1; fd = -1;
} }
}
if (saved_question) if (do_forward && saved_question)
{
if (m == 0)
{ {
/* Get the question back, since it may have been mangled by answer_request() */ /* Get the question back, since it may have been mangled by answer_request() */
blockdata_retrieve(saved_question, (size_t)n, (void *)header); blockdata_retrieve(saved_question, (size_t)n, (void *)header);
blockdata_free(saved_question); blockdata_free(saved_question);
saved_question = NULL;
if (forward_query(fd, &source_addr, &dst_addr, if_index, header, (size_t)n, if (forward_query(fd, &source_addr, &dst_addr, if_index, header, (size_t)n,
udp_size, now, NULL, ad_reqd, do_bit, 0)) udp_size, now, NULL, ad_reqd, do_bit, 0))
daemon->metrics[METRIC_DNS_QUERIES_FORWARDED]++; daemon->metrics[METRIC_DNS_QUERIES_FORWARDED]++;
else else
daemon->metrics[METRIC_DNS_LOCAL_ANSWERED]++; daemon->metrics[METRIC_DNS_LOCAL_ANSWERED]++;
} }
else
blockdata_free(saved_question); blockdata_free(saved_question);
}
}
} }
/* Send query in packet, qsize to a server determined by first,last,start and /* Send query in packet, qsize to a server determined by first,last,start and
get the reply. return reply size. */ get the reply. return reply size. */
static ssize_t tcp_talk(int first, int last, int start, unsigned char *packet, size_t qsize, static ssize_t tcp_talk(int first, int last, int start, unsigned char *packet, size_t qsize,
@@ -2215,19 +2205,17 @@ unsigned char *tcp_request(int confd, time_t now,
union mysockaddr *local_addr, struct in_addr netmask, int auth_dns) union mysockaddr *local_addr, struct in_addr netmask, int auth_dns)
{ {
size_t size = 0, saved_size = 0; size_t size = 0, saved_size = 0;
int norebind; int norebind = 0;
#ifdef HAVE_CONNTRACK #ifdef HAVE_CONNTRACK
int is_single_query = 0, allowed = 1; int allowed = 1;
#endif #endif
#ifdef HAVE_AUTH #ifdef HAVE_AUTH
int local_auth = 0; int local_auth = 0;
#endif #endif
int checking_disabled, do_bit, added_pheader = 0, have_pseudoheader = 0; int checking_disabled, do_bit = 0, ad_reqd = 0, added_pheader = 0, have_pseudoheader = 0;
int cacheable, no_cache_dnssec = 0, cache_secure = 0, bogusanswer = 0;
size_t m;
struct blockdata *saved_question = NULL; struct blockdata *saved_question = NULL;
unsigned short qtype; unsigned short qtype;
unsigned int gotname; unsigned int gotname = 0;
/* Max TCP packet + slop + size */ /* Max TCP packet + slop + size */
unsigned char *packet = whine_malloc(65536 + MAXDNAME + RRFIXEDSZ + sizeof(u16)); unsigned char *packet = whine_malloc(65536 + MAXDNAME + RRFIXEDSZ + sizeof(u16));
unsigned char *payload = &packet[2]; unsigned char *payload = &packet[2];
@@ -2243,8 +2231,7 @@ unsigned char *tcp_request(int confd, time_t now,
unsigned char *pheader; unsigned char *pheader;
unsigned int mark = 0; unsigned int mark = 0;
int have_mark = 0; int have_mark = 0;
int first, last, filtered, stale, do_stale = 0; int first, last, filtered, do_stale = 0;
unsigned int flags = 0;
if (!packet || getpeername(confd, (struct sockaddr *)&peer_addr, &peer_len) == -1) if (!packet || getpeername(confd, (struct sockaddr *)&peer_addr, &peer_len) == -1)
return packet; return packet;
@@ -2297,9 +2284,12 @@ unsigned char *tcp_request(int confd, time_t now,
while (1) while (1)
{ {
int ede = EDE_UNSET; int stale = 0, ede = EDE_UNSET;
size_t m = 0;
stale = 0; unsigned int flags = 0;
#ifdef HAVE_AUTH
struct auth_zone *zone;
#endif
if (!do_stale) if (!do_stale)
{ {
@@ -2310,7 +2300,6 @@ unsigned char *tcp_request(int confd, time_t now,
!(size = ntohs(tcp_len)) || !(size = ntohs(tcp_len)) ||
!read_write(confd, payload, size, RW_READ)) !read_write(confd, payload, size, RW_READ))
break; break;
}
if (size < (int)sizeof(struct dns_header)) if (size < (int)sizeof(struct dns_header))
continue; continue;
@@ -2327,29 +2316,22 @@ unsigned char *tcp_request(int confd, time_t now,
daemon->log_display_id = -(++daemon->log_id); daemon->log_display_id = -(++daemon->log_id);
daemon->log_source_addr = &peer_addr; daemon->log_source_addr = &peer_addr;
/* save state of "cd" flag in query */
if ((checking_disabled = header->hb4 & HB4_CD))
no_cache_dnssec = 1;
if (OPCODE(header) != QUERY) if (OPCODE(header) != QUERY)
{ {
log_query_mysockaddr(F_QUERY | F_FORWARD, "opcode", &peer_addr, "non-query", 0); log_query_mysockaddr(F_QUERY | F_FORWARD, "opcode", &peer_addr, "non-query", 0);
gotname = 0; gotname = 0;
m = 0;
flags = F_RCODE; flags = F_RCODE;
} }
else if ((gotname = extract_request(header, (unsigned int)size, daemon->namebuff, &qtype))) else if (!(gotname = extract_request(header, (unsigned int)size, daemon->namebuff, &qtype)))
ede = EDE_INVALID_DATA;
else
{ {
#ifdef HAVE_AUTH if (saved_question)
struct auth_zone *zone; blockdata_free(saved_question);
#endif
#ifdef HAVE_CONNTRACK saved_question = blockdata_alloc((char *)header, (size_t)size);
is_single_query = 1; saved_size = size;
#endif
if (!do_stale)
{
log_query_mysockaddr(F_QUERY | F_FORWARD, daemon->namebuff, log_query_mysockaddr(F_QUERY | F_FORWARD, daemon->namebuff,
&peer_addr, auth_dns ? "auth" : "query", qtype); &peer_addr, auth_dns ? "auth" : "query", qtype);
@@ -2364,7 +2346,6 @@ unsigned char *tcp_request(int confd, time_t now,
break; break;
} }
#endif #endif
}
norebind = domain_no_rebind(daemon->namebuff); norebind = domain_no_rebind(daemon->namebuff);
@@ -2377,101 +2358,77 @@ unsigned char *tcp_request(int confd, time_t now,
if (find_pseudoheader(header, (size_t)size, NULL, &pheader, NULL, NULL)) if (find_pseudoheader(header, (size_t)size, NULL, &pheader, NULL, NULL))
{ {
unsigned short flags; unsigned short ede_flags;
have_pseudoheader = 1; have_pseudoheader = 1;
pheader += 4; /* udp_size, ext_rcode */ pheader += 4; /* udp_size, ext_rcode */
GETSHORT(flags, pheader); GETSHORT(ede_flags, pheader);
if (flags & 0x8000) if (ede_flags & 0x8000)
do_bit = 1; /* do bit */ do_bit = 1; /* do bit */
} }
ad_reqd = do_bit;
/* RFC 6840 5.7 */
if (header->hb4 & HB4_AD)
ad_reqd = 1;
#ifdef HAVE_CONNTRACK #ifdef HAVE_CONNTRACK
#ifdef HAVE_AUTH #ifdef HAVE_AUTH
if (!auth_dns || local_auth) if (!auth_dns || local_auth)
#endif #endif
if (option_bool(OPT_CMARK_ALST_EN) && have_mark && ((u32)mark & daemon->allowlist_mask)) if (option_bool(OPT_CMARK_ALST_EN) && have_mark && ((u32)mark & daemon->allowlist_mask))
allowed = is_query_allowed_for_mark((u32)mark, is_single_query ? daemon->namebuff : NULL); allowed = is_query_allowed_for_mark((u32)mark, daemon->namebuff);
#endif #endif
if (0); if (0);
#ifdef HAVE_CONNTRACK #ifdef HAVE_CONNTRACK
else if (!allowed) else if (!allowed)
{ {
u16 swap = htons(EDE_BLOCKED); ede = EDE_BLOCKED;
m = answer_disallowed(header, size, (u32)mark, daemon->namebuff);
m = answer_disallowed(header, size, (u32)mark, is_single_query ? daemon->namebuff : NULL);
if (have_pseudoheader && m != 0)
m = add_pseudoheader(header, m, ((unsigned char *) header) + 65536,
EDNS0_OPTION_EDE, (unsigned char *)&swap, 2, do_bit, 0);
} }
#endif #endif
#ifdef HAVE_AUTH #ifdef HAVE_AUTH
else if (auth_dns) else if (auth_dns)
{
m = answer_auth(header, ((char *) header) + 65536, (size_t)size, now, &peer_addr, local_auth); m = answer_auth(header, ((char *) header) + 65536, (size_t)size, now, &peer_addr, local_auth);
if (m >= 1 && have_pseudoheader)
m = add_pseudoheader(header, m, ((unsigned char *) header) + 65536,
0, NULL, 0, do_bit, 0);
}
#endif #endif
else else
{
int ad_reqd = do_bit;
/* RFC 6840 5.7 */
if (header->hb4 & HB4_AD)
ad_reqd = 1;
if (do_stale)
m = 0;
else
{
if (saved_question)
blockdata_free(saved_question);
saved_question = blockdata_alloc((char *)header, (size_t)size);
saved_size = size;
/* m > 0 if answered from cache */
m = answer_request(header, ((char *) header) + 65536, (size_t)size, m = answer_request(header, ((char *) header) + 65536, (size_t)size,
dst_addr_4, netmask, now, ad_reqd, do_bit, &stale, &filtered); dst_addr_4, netmask, now, ad_reqd, do_bit, &stale, &filtered);
}
if (m >= 1 && have_pseudoheader)
m = add_pseudoheader(header, m, ((unsigned char *) header) + 65536,
0, NULL, 0, do_bit, 0);
} }
/* Do this by steam now we're not in the select() loop */ /* Do this by steam now we're not in the select() loop */
check_log_writer(1); check_log_writer(1);
if (m == 0 && saved_question) if (m == 0 && ede == EDE_UNSET && saved_question)
{ {
struct server *master; struct server *master;
int start; int start;
int cacheable, no_cache_dnssec = 0, cache_secure = 0, bogusanswer = 0;
blockdata_retrieve(saved_question, (size_t)saved_size, header); blockdata_retrieve(saved_question, (size_t)saved_size, header);
size = saved_size; size = saved_size;
/* save state of "cd" flag in query */
if ((checking_disabled = header->hb4 & HB4_CD))
no_cache_dnssec = 1;
if (lookup_domain(daemon->namebuff, gotname, &first, &last)) if (lookup_domain(daemon->namebuff, gotname, &first, &last))
flags = is_local_answer(now, first, daemon->namebuff); flags = is_local_answer(now, first, daemon->namebuff);
else else
{
/* No configured servers */
ede = EDE_NOT_READY; ede = EDE_NOT_READY;
flags = 0;
}
if (!flags && ede == EDE_UNSET)
{
/* don't forward A or AAAA queries for simple names, except the empty name */ /* don't forward A or AAAA queries for simple names, except the empty name */
if (!flags && if (option_bool(OPT_NODOTS_LOCAL) &&
option_bool(OPT_NODOTS_LOCAL) &&
(gotname & (F_IPV4 | F_IPV6)) && (gotname & (F_IPV4 | F_IPV6)) &&
!strchr(daemon->namebuff, '.') && !strchr(daemon->namebuff, '.') &&
strlen(daemon->namebuff) != 0) strlen(daemon->namebuff) != 0)
flags = check_for_local_domain(daemon->namebuff, now) ? F_NOERR : F_NXDOMAIN; flags = check_for_local_domain(daemon->namebuff, now) ? F_NOERR : F_NXDOMAIN;
else
if (!flags && ede != EDE_NOT_READY)
{ {
master = daemon->serverarray[first]; master = daemon->serverarray[first];
@@ -2501,11 +2458,9 @@ unsigned char *tcp_request(int confd, time_t now,
/* Loop round available servers until we succeed in connecting to one. */ /* Loop round available servers until we succeed in connecting to one. */
if ((m = tcp_talk(first, last, start, packet, size, have_mark, mark, &serv)) == 0) if ((m = tcp_talk(first, last, start, packet, size, have_mark, mark, &serv)) == 0)
{
ede = EDE_NETERR; ede = EDE_NETERR;
break; else
} {
/* get query name again for logging - may have been overwritten */ /* get query name again for logging - may have been overwritten */
if (!(gotname = extract_request(header, (unsigned int)size, daemon->namebuff, &qtype))) if (!(gotname = extract_request(header, (unsigned int)size, daemon->namebuff, &qtype)))
strcpy(daemon->namebuff, "query"); strcpy(daemon->namebuff, "query");
@@ -2561,6 +2516,7 @@ unsigned char *tcp_request(int confd, time_t now,
} }
#endif #endif
/* restore CD bit to the value in the query */ /* restore CD bit to the value in the query */
if (checking_disabled) if (checking_disabled)
header->hb4 |= HB4_CD; header->hb4 |= HB4_CD;
@@ -2575,6 +2531,9 @@ unsigned char *tcp_request(int confd, time_t now,
m = process_reply(header, now, serv, (unsigned int)m, m = process_reply(header, now, serv, (unsigned int)m,
option_bool(OPT_NO_REBIND) && !norebind, no_cache_dnssec, cache_secure, bogusanswer, option_bool(OPT_NO_REBIND) && !norebind, no_cache_dnssec, cache_secure, bogusanswer,
ad_reqd, do_bit, added_pheader, &peer_addr, ((unsigned char *)header) + 65536, ede); ad_reqd, do_bit, added_pheader, &peer_addr, ((unsigned char *)header) + 65536, ede);
/* process_reply() adds pheader itself */
have_pseudoheader = 0;
} }
} }
} }
@@ -2590,10 +2549,8 @@ unsigned char *tcp_request(int confd, time_t now,
((char *) header) + 65536, first, last, ede))) ((char *) header) + 65536, first, last, ede)))
break; break;
} }
else else if (ede == EDE_UNSET)
{ {
ede = EDE_UNSET;
if (filtered) if (filtered)
ede = EDE_FILTERED; ede = EDE_FILTERED;
else if (stale) else if (stale)
@@ -2621,6 +2578,7 @@ unsigned char *tcp_request(int confd, time_t now,
if (option_bool(OPT_CMARK_ALST_EN) && have_mark && ((u32)mark & daemon->allowlist_mask)) if (option_bool(OPT_CMARK_ALST_EN) && have_mark && ((u32)mark & daemon->allowlist_mask))
report_addresses(header, m, mark); report_addresses(header, m, mark);
#endif #endif
if (!read_write(confd, packet, m + sizeof(u16), RW_WRITE)) if (!read_write(confd, packet, m + sizeof(u16), RW_WRITE))
break; break;
@@ -2633,6 +2591,8 @@ unsigned char *tcp_request(int confd, time_t now,
shutdown(confd, SHUT_RDWR); shutdown(confd, SHUT_RDWR);
close(confd); close(confd);
do_stale = 1; do_stale = 1;
/* Don't mark the query with the source when refreshing stale data. */
daemon->log_source_addr = NULL;
} }
} }
+16 -2
View File
@@ -810,11 +810,25 @@ void close_fds(long max_fd, int spare1, int spare2, int spare3)
{ {
/* On Linux, use the /proc/ filesystem to find which files /* On Linux, use the /proc/ filesystem to find which files
are actually open, rather than iterate over the whole space, are actually open, rather than iterate over the whole space,
for efficiency reasons. If this fails we drop back to the dumb code. */ for efficiency reasons.
On *BSD, the same facility is found at /dev/fd.
If this fails we drop back to the dumb code.
*/
#ifdef HAVE_LINUX_NETWORK #ifdef HAVE_LINUX_NETWORK
#define FDESCFS "/proc/self/fd"
#endif
#ifdef HAVE_BSD_NETWORK
#define FDESCFS "/dev/fd"
#endif
#ifdef FDESCFS
DIR *d; DIR *d;
if ((d = opendir("/proc/self/fd"))) if ((d = opendir(FDESCFS)))
{ {
struct dirent *de; struct dirent *de;