mirror of
http://thekelleys.org.uk/git/dnsmasq.git
synced 2026-11-11 16:40:27 +00:00
Compare commits
7
Commits
v2.91test1
...
v2.91test2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0f437b3b5e | ||
|
|
8a5fe8ce6b | ||
|
|
2a664c03db | ||
|
|
4902807879 | ||
|
|
742af6e4b9 | ||
|
|
3eb008c36d | ||
|
|
32248ebd5b |
No files matched your search
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user