Implement "DNS-0x20 encoding".

This provides extra protection against reply-spoof attacks.

Since DNS queries are case-insensitive, it's possible to randomly flip
the case of letters in a query and still get the correct answer back.
This adds an extra dimension for a cache-poisoning attacker to guess
when sending replies in-the-blind since it's expected that the
legitimate answer will have the same pattern of upper and lower case
as the query, so any replies which don't can be ignored as
malicious.

The amount of extra entropy clearly depends on the number
of a-z and A-Z characters in the query, and this implementation puts a
hard limit of 32 bits to make rescource allocation easy. This about
doubles entropy over the standard random ID and random port
combination.
This commit is contained in:
Simon Kelley
2025-01-19 21:44:19 +00:00
parent 65f9c1aca1
commit 995a16ca0c
6 changed files with 113 additions and 66 deletions

View File

@@ -137,7 +137,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
nameoffset = p - (unsigned char *)header;
/* now extract name as .-concatenated string into name */
if (!extract_name(header, qlen, &p, name, 1, 4))
if (!extract_name(header, qlen, &p, name, EXTR_NAME_EXTRACT, 4))
return 0; /* bad packet */
GETSHORT(qtype, p);

View File

@@ -790,6 +790,7 @@ struct frec {
int forwardall, flags;
time_t time;
u32 forward_timestamp;
unsigned int encode_bitmap;
int forward_delay;
struct blockdata *stash; /* saved query or saved reply, whilst we validate */
size_t stash_len;
@@ -1386,7 +1387,7 @@ int is_rev_synth(int flag, union all_addr *addr, char *name);
/* rfc1035.c */
int do_doctor(struct dns_header *header, size_t qlen, char *namebuff);
int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
char *name, int isExtract, int extrabytes);
char *name, int func, unsigned int parm);
unsigned char *skip_name(unsigned char *ansp, struct dns_header *header, size_t plen, int extrabytes);
unsigned char *skip_questions(struct dns_header *header, size_t plen);
unsigned char *skip_section(unsigned char *ansp, int count, struct dns_header *header, size_t plen);
@@ -1413,6 +1414,11 @@ int add_resource_record(struct dns_header *header, char *limit, int *truncp,
int *offset, unsigned short type, unsigned short class, char *format, ...);
int in_arpa_name_2_addr(char *namein, union all_addr *addrp);
int private_net(struct in_addr addr, int ban_localhost);
/* extract_name ops */
#define EXTR_NAME_EXTRACT 1
#define EXTR_NAME_COMPARE 2
#define EXTR_NAME_NOCASE 3
#define EXTR_NAME_FLIP 4
/* auth.c */
#ifdef HAVE_AUTH

View File

@@ -191,7 +191,7 @@ static int get_rdata(struct dns_header *header, size_t plen, struct rdata_state
/* domain-name, canonicalise */
int len;
if (!extract_name(header, plen, &state->ip, state->buff, 1, 0) ||
if (!extract_name(header, plen, &state->ip, state->buff, EXTR_NAME_EXTRACT, 0) ||
(len = to_wire(state->buff)) == 0)
continue;
@@ -339,7 +339,7 @@ static int explore_rrset(struct dns_header *header, size_t plen, int class, int
pstart = p;
if (!(res = extract_name(header, plen, &p, name, 0, 10)))
if (!(res = extract_name(header, plen, &p, name, EXTR_NAME_COMPARE, 10)))
return 0; /* bad packet */
GETSHORT(stype, p);
@@ -374,14 +374,14 @@ static int explore_rrset(struct dns_header *header, size_t plen, int class, int
if (gotkey)
{
/* If there's more than one SIG, ensure they all have same keyname */
if (extract_name(header, plen, &p, keyname, 0, 0) != 1)
if (extract_name(header, plen, &p, keyname, EXTR_NAME_COMPARE, 0) != 1)
return 0;
}
else
{
gotkey = 1;
if (!extract_name(header, plen, &p, keyname, 1, 0))
if (!extract_name(header, plen, &p, keyname, EXTR_NAME_EXTRACT, 0))
return 0;
/* RFC 4035 5.3.1 says that the Signer's Name field MUST equal
@@ -503,7 +503,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
GETLONG(sig_inception, p);
GETSHORT(key_tag, p);
if (!extract_name(header, plen, &p, keyname, 1, 0))
if (!extract_name(header, plen, &p, keyname, EXTR_NAME_EXTRACT, 0))
return STAT_BOGUS;
if (!time_check)
@@ -568,7 +568,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
p = rrset[i];
if (!extract_name(header, plen, &p, name, 1, 10))
if (!extract_name(header, plen, &p, name, EXTR_NAME_EXTRACT, 10))
return STAT_BOGUS;
name_start = name;
@@ -661,7 +661,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
/* namebuff used for workspace above, restore to leave unchanged on exit */
p = (unsigned char*)(rrset[0]);
if (!extract_name(header, plen, &p, name, 1, 0))
if (!extract_name(header, plen, &p, name, EXTR_NAME_EXTRACT, 0))
return STAT_BOGUS;
if (key)
@@ -727,7 +727,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
static unsigned char **cached_digest;
static size_t cached_digest_size = 0;
if (ntohs(header->qdcount) != 1 || RCODE(header) != NOERROR || !extract_name(header, plen, &p, name, 1, 4))
if (ntohs(header->qdcount) != 1 || RCODE(header) != NOERROR || !extract_name(header, plen, &p, name, EXTR_NAME_EXTRACT, 4))
return STAT_BOGUS | DNSSEC_FAIL_NOKEY;
GETSHORT(qtype, p);
@@ -752,7 +752,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
for (j = ntohs(header->ancount); j != 0; j--)
{
/* Ensure we have type, class TTL and length */
if (!(rc = extract_name(header, plen, &p, name, 0, 10)))
if (!(rc = extract_name(header, plen, &p, name, EXTR_NAME_COMPARE, 10)))
return STAT_BOGUS; /* bad packet */
GETSHORT(qtype, p);
@@ -904,7 +904,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
for (j = ntohs(header->ancount); j != 0; j--)
{
/* Ensure we have type, class TTL and length */
if (!(rc = extract_name(header, plen, &p, name, 0, 10)))
if (!(rc = extract_name(header, plen, &p, name, EXTR_NAME_COMPARE, 10)))
return STAT_BOGUS; /* bad packet */
GETSHORT(qtype, p);
@@ -1024,7 +1024,7 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
}
p = (unsigned char *)(header+1);
if (!extract_name(header, plen, &p, name, 1, 4))
if (!extract_name(header, plen, &p, name, EXTR_NAME_EXTRACT, 4))
return STAT_BOGUS;
p += 4; /* qtype, qclass */
@@ -1050,7 +1050,7 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
{
unsigned char *psave;
if (!(rc = extract_name(header, plen, &p, name, 0, 10)))
if (!(rc = extract_name(header, plen, &p, name, EXTR_NAME_COMPARE, 10)))
return STAT_BOGUS; /* bad packet */
GETSHORT(atype, p);
@@ -1231,12 +1231,12 @@ static int prove_non_existence_nsec(struct dns_header *header, size_t plen, unsi
int sig_labels, name_labels;
p = nsecs[i];
if (!extract_name(header, plen, &p, workspace1, 1, 10))
if (!extract_name(header, plen, &p, workspace1, EXTR_NAME_EXTRACT, 10))
return DNSSEC_FAIL_BADPACKET;
p += 8; /* class, type, TTL */
GETSHORT(rdlen, p);
psave = p;
if (!extract_name(header, plen, &p, workspace2, 1, 0))
if (!extract_name(header, plen, &p, workspace2, EXTR_NAME_EXTRACT, 0))
return DNSSEC_FAIL_BADPACKET;
/* If NSEC comes from wildcard expansion, use original wildcard
@@ -1400,7 +1400,7 @@ static int check_nsec3_coverage(struct dns_header *header, size_t plen, int dige
for (i = 0; i < nsec_count; i++)
if ((p = nsecs[i]))
{
if (!extract_name(header, plen, &p, workspace1, 1, 10) ||
if (!extract_name(header, plen, &p, workspace1, EXTR_NAME_EXTRACT, 10) ||
!(base32_len = base32_decode(workspace1, (unsigned char *)workspace2)))
return 0;
@@ -1609,7 +1609,7 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns
for (i = 0; i < nsec_count; i++)
if ((p = nsecs[i]))
{
if (!extract_name(header, plen, &p, workspace1, 1, 0))
if (!extract_name(header, plen, &p, workspace1, EXTR_NAME_EXTRACT, 0))
return DNSSEC_FAIL_BADPACKET;
if (!(base32_len = base32_decode(workspace1, (unsigned char *)workspace2)))
@@ -1684,7 +1684,7 @@ static int prove_non_existence(struct dns_header *header, size_t plen, char *key
{
unsigned char *pstart = p;
if (!extract_name(header, plen, &p, daemon->workspacename, 1, 10))
if (!extract_name(header, plen, &p, daemon->workspacename, EXTR_NAME_EXTRACT, 10))
return DNSSEC_FAIL_BADPACKET;
GETSHORT(type, p);
@@ -1735,7 +1735,7 @@ static int prove_non_existence(struct dns_header *header, size_t plen, char *key
{
unsigned char *psav;
if (!(res = extract_name(header, plen, &p1, daemon->workspacename, 0, 10)))
if (!(res = extract_name(header, plen, &p1, daemon->workspacename, EXTR_NAME_COMPARE, 10)))
return DNSSEC_FAIL_BADPACKET;
GETSHORT(type1, p1);
@@ -1965,7 +1965,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
targets[0] = p1;
targetidx = 1;
if (!extract_name(header, plen, &p1, name, 1, 4))
if (!extract_name(header, plen, &p1, name, EXTR_NAME_EXTRACT, 4))
return STAT_BOGUS;
GETSHORT(qtype, p1);
@@ -2003,7 +2003,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
if (i != 0 && !ADD_RDLEN(header, p1, plen, rdlen1))
return STAT_BOGUS;
if (!extract_name(header, plen, &p1, name, 1, 10))
if (!extract_name(header, plen, &p1, name, EXTR_NAME_EXTRACT, 10))
return STAT_BOGUS; /* bad packet */
GETSHORT(type1, p1);
@@ -2018,7 +2018,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
/* Check if we've done this RRset already */
for (p2 = ans_start, j = 0; j < i; j++)
{
if (!(rc = extract_name(header, plen, &p2, name, 0, 10)))
if (!(rc = extract_name(header, plen, &p2, name, EXTR_NAME_COMPARE, 10)))
return STAT_BOGUS; /* bad packet */
GETSHORT(type2, p2);
@@ -2115,7 +2115,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
if ((p2 = targets[j]))
{
int rc1;
if (!(rc1 = extract_name(header, plen, &p2, name, 0, 10)))
if (!(rc1 = extract_name(header, plen, &p2, name, EXTR_NAME_COMPARE, 10)))
return STAT_BOGUS; /* bad packet */
if (class1 == qclass && rc1 == 1 && (type1 == T_CNAME || type1 == qtype || qtype == T_ANY ))
@@ -2149,7 +2149,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
if (neganswer)
*neganswer = 1;
if (!extract_name(header, plen, &p2, name, 1, 10))
if (!extract_name(header, plen, &p2, name, EXTR_NAME_EXTRACT, 10))
return STAT_BOGUS; /* bad packet */
/* NXDOMAIN or NODATA reply, unanswered question is (name, qclass, qtype) */

View File

@@ -264,6 +264,8 @@ static void forward_query(int udpfd, union mysockaddr *udpaddr,
/* new query */
if (!forward)
{
unsigned char *p;
if (OPCODE(header) != QUERY)
{
flags = F_RCODE;
@@ -323,7 +325,12 @@ static void forward_query(int udpfd, union mysockaddr *udpaddr,
forward->frec_src.orig_id = ntohs(header->id);
forward->new_id = get_id();
header->id = ntohs(forward->new_id);
forward->encode_bitmap = rand32();
p = (unsigned char *)(header+1);
if (!extract_name(header, plen, &p, NULL, EXTR_NAME_FLIP, forward->encode_bitmap))
goto reply;
/* Keep copy of query for retries and move to TCP */
if (!(forward->stash = blockdata_alloc((char *)header, plen)))
{
@@ -968,7 +975,8 @@ static void dnssec_validate(struct frec *forward, struct dns_header *header,
new->flags &= ~(FREC_DNSKEY_QUERY | FREC_DS_QUERY);
new->flags |= flags;
new->forwardall = 0;
new->encode_bitmap = 0;
forward->next_dependent = NULL;
new->dependent = forward; /* to find query awaiting new one. */
@@ -1085,7 +1093,7 @@ void reply_query(int fd, time_t now)
return;
p = (unsigned char *)(header+1);
if (!extract_name(header, n, &p, daemon->namebuff, 1, 4))
if (!extract_name(header, n, &p, daemon->namebuff, EXTR_NAME_EXTRACT, 4))
return; /* bad packet */
GETSHORT(rrtype, p);
GETSHORT(class, p);
@@ -1195,7 +1203,11 @@ void reply_query(int fd, time_t now)
/* denominator controls how many queries we average over. */
server->query_latency = server->mma_latency/128;
/* Flip the bits back in the query name. */
p = (unsigned char *)(header+1);
if (!extract_name(header, n, &p, NULL, EXTR_NAME_FLIP, forward->encode_bitmap))
return;
#ifdef HAVE_DNSSEC
if (option_bool(OPT_DNSSEC_VALID))
{
@@ -1895,7 +1907,7 @@ static ssize_t tcp_talk(int first, int last, int start, unsigned char *packet,
/* Save the query to make sure we get the answer we expect. */
p = (unsigned char *)(header+1);
if (!extract_name(header, qsize, &p, daemon->namebuff, 1, 4))
if (!extract_name(header, qsize, &p, daemon->namebuff, EXTR_NAME_EXTRACT, 4))
return 0;
GETSHORT(type, p);
GETSHORT(class, p);
@@ -2006,7 +2018,7 @@ static ssize_t tcp_talk(int first, int last, int start, unsigned char *packet,
DNS-0x20 encoding is effective.
Try another server, or give up */
p = (unsigned char *)(header+1);
if (extract_name(header, rsize, &p, daemon->namebuff, -1, 4) != 1)
if (extract_name(header, rsize, &p, daemon->namebuff, EXTR_NAME_NOCASE, 4) != 1)
continue;
GETSHORT(rtype, p);
GETSHORT(rclass, p);
@@ -3049,7 +3061,7 @@ static struct frec *lookup_frec(char *target, int class, int rrtype, int id, int
int hclass, hrrtype;
/* Case sensitive compare for DNS-0x20 encoding. */
if (extract_name(header, f->stash_len, &p, target, -1, 4) != 1)
if (extract_name(header, f->stash_len, &p, target, EXTR_NAME_NOCASE, 4) != 1)
continue;
GETSHORT(hrrtype, p);

View File

@@ -16,26 +16,29 @@
#include "dnsmasq.h"
/* isExtract == 1 -> extract name
isExtract == 0 -> compare name, case insensitive
isExtract == -1 -> compare name, case sensitive
/* EXTR_NAME_EXTRACT -> extract name
EXTR_NAME_COMPARE -> compare name, case insensitive
EXTR_NAME_NOCASE -> compare name, case sensitive
EXTR_NAME_FLIP -> flip 0x20 bits in packet, controlled by bitmap in parm. name may be NULL
return = 0 -> error
return = 1 -> extract OK, compare OK
return = 1 -> extract OK, compare OK, flip OK
return = 2 -> extract OK, compare failed.
*/
int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
char *name, int isExtract, int extrabytes)
char *name, int func, unsigned int parm)
{
unsigned char *cp = (unsigned char *)name, *p = *pp, *p1 = NULL;
unsigned int j, l, namelen = 0, hops = 0;
int retvalue = 1, case_insens = 1;
if (isExtract == -1)
isExtract = case_insens = 0;
else if (isExtract)
*cp = 0;
int retvalue = 1, case_insens = 1, isExtract = 0, flip = 0, extrabytes = (int)parm;
if (func == EXTR_NAME_EXTRACT)
isExtract = 1, *cp = 0;
else if (func == EXTR_NAME_NOCASE)
case_insens = 0;
else if (func == EXTR_NAME_FLIP)
flip = 1, extrabytes = 0;
while (1)
{
unsigned int label_type;
@@ -56,7 +59,7 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
cp--;
*cp = 0; /* terminate: lose final period */
}
else if (*cp != 0)
else if (!flip && *cp != 0)
retvalue = 2;
if (p1) /* we jumped via compression */
@@ -95,7 +98,7 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
if (!CHECK_LEN(header, p, plen, l))
return 0;
for(j=0; j<l; j++, p++)
for (j=0; j<l; j++, p++)
if (isExtract)
{
unsigned char c = *p;
@@ -108,6 +111,18 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
else
*cp++ = c;
}
else if (flip)
{
unsigned char c = *p;
/* parm is unsigned. We only flip up to the first 32 alpha-chars. */
if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
{
if (parm & 1)
*p ^= 0x20;
parm >>= 1;
}
}
else
{
unsigned char c1 = *cp, c2 = *p;
@@ -117,15 +132,15 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
else
{
cp++;
if (case_insens && c1 >= 'A' && c1 <= 'Z')
c1 += 'a' - 'A';
if (c1 == NAME_ESCAPE)
c1 = (*cp++)-1;
else if (case_insens && c1 >= 'A' && c1 <= 'Z')
c1 += 'a' - 'A';
if (case_insens && c2 >= 'A' && c2 <= 'Z')
c2 += 'a' - 'A';
if (c1 != c2)
retvalue = 2;
}
@@ -133,7 +148,7 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
if (isExtract)
*cp++ = '.';
else if (*cp != 0 && *cp++ != '.')
else if (!flip && *cp != 0 && *cp++ != '.')
retvalue = 2;
}
else
@@ -409,7 +424,7 @@ int do_doctor(struct dns_header *header, size_t qlen, char *namebuff)
if (i == ntohs(header->ancount) && !(p = skip_section(p, ntohs(header->nscount), header, qlen)))
return done;
if (!extract_name(header, qlen, &p, namebuff, 1, 10))
if (!extract_name(header, qlen, &p, namebuff, EXTR_NAME_EXTRACT, 10))
return done; /* bad packet */
GETSHORT(qtype, p);
@@ -490,7 +505,7 @@ static int find_soa(struct dns_header *header, size_t qlen, char *name, int *sub
for (i = 0; i < ntohs(header->nscount); i++)
{
if (!extract_name(header, qlen, &p, daemon->workspacename, 1, 0))
if (!extract_name(header, qlen, &p, daemon->workspacename, EXTR_NAME_EXTRACT, 0))
return 0; /* bad packet */
GETSHORT(qtype, p);
@@ -519,7 +534,7 @@ static int find_soa(struct dns_header *header, size_t qlen, char *name, int *sub
for (j = 0; j < 2; j++) /* MNAME, RNAME */
{
if (!extract_name(header, qlen, &p, daemon->workspacename, 1, 0))
if (!extract_name(header, qlen, &p, daemon->workspacename, EXTR_NAME_EXTRACT, 0))
{
if (!no_cache)
blockdata_free(addr.rrblock.rrdata);
@@ -670,7 +685,7 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
namep = p = (unsigned char *)(header+1);
if (ntohs(header->qdcount) != 1 || !extract_name(header, qlen, &p, name, 1, 4))
if (ntohs(header->qdcount) != 1 || !extract_name(header, qlen, &p, name, EXTR_NAME_EXTRACT, 4))
return 2; /* bad packet */
GETSHORT(qtype, p);
@@ -694,7 +709,7 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
for (j = 0; j < ntohs(header->ancount); j++)
{
int secflag = 0;
if (!(res = extract_name(header, qlen, &p1, name, 0, 10)))
if (!(res = extract_name(header, qlen, &p1, name, EXTR_NAME_COMPARE, 10)))
return 2; /* bad packet */
GETSHORT(aqtype, p1);
@@ -732,7 +747,7 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
if (aqtype == T_CNAME)
log_query(secflag | F_CNAME | F_FORWARD | F_UPSTREAM, name, NULL, NULL, 0);
if (!extract_name(header, qlen, &p1, name, 1, 0))
if (!extract_name(header, qlen, &p1, name, EXTR_NAME_EXTRACT, 0))
return 2;
if (aqtype == T_CNAME)
@@ -810,7 +825,7 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
{
int secflag = 0;
if (!(res = extract_name(header, qlen, &p1, name, 0, 10)))
if (!(res = extract_name(header, qlen, &p1, name, EXTR_NAME_COMPARE, 10)))
return 2; /* bad packet */
GETSHORT(aqtype, p1);
@@ -872,7 +887,7 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
}
namep = p1;
if (!extract_name(header, qlen, &p1, name, 1, 0))
if (!extract_name(header, qlen, &p1, name, EXTR_NAME_EXTRACT, 0))
return 2;
if (qtype != T_CNAME)
@@ -942,7 +957,7 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
/* Name, extract it then re-encode. */
int len;
if (!extract_name(header, qlen, &p1, name, 1, 0))
if (!extract_name(header, qlen, &p1, name, EXTR_NAME_EXTRACT, 0))
{
blockdata_free(addr.rrblock.rrdata);
return 2;
@@ -975,7 +990,7 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
} while (desc != -1);
/* we overwrote the original name, so get it back here. */
if (!extract_name(header, qlen, &tmp, name, 1, 0))
if (!extract_name(header, qlen, &tmp, name, EXTR_NAME_EXTRACT, 0))
{
blockdata_free(addr.rrblock.rrdata);
return 2;
@@ -1137,7 +1152,7 @@ void report_addresses(struct dns_header *header, size_t len, u32 mark)
{
int aqtype, aqclass, ardlen;
if (!extract_name(header, len, &p, daemon->namebuff, 1, 10))
if (!extract_name(header, len, &p, daemon->namebuff, EXTR_NAME_EXTRACT, 10))
return;
if (!CHECK_LEN(header, p, len, 10))
@@ -1155,7 +1170,7 @@ void report_addresses(struct dns_header *header, size_t len, u32 mark)
{
if (aqtype == T_CNAME)
{
if (!extract_name(header, len, &p, daemon->workspacename, 1, 0))
if (!extract_name(header, len, &p, daemon->workspacename, EXTR_NAME_EXTRACT, 0))
return;
if (safe_name(daemon->namebuff) && safe_name(daemon->workspacename))
ubus_event_bcast_connmark_allowlist_resolved(mark, daemon->namebuff, daemon->workspacename, attl);
@@ -1205,7 +1220,7 @@ unsigned int extract_request(struct dns_header *header, size_t qlen, char *name,
if (!(header->hb3 & HB3_QR) && (ntohs(header->ancount) != 0 || ntohs(header->nscount) != 0))
return 0; /* non-standard query. */
if (!extract_name(header, qlen, &p, name, 1, 4))
if (!extract_name(header, qlen, &p, name, EXTR_NAME_EXTRACT, 4))
return 0; /* bad packet */
GETSHORT(qtype, p);
@@ -1319,7 +1334,7 @@ static int check_bad_address(struct dns_header *header, size_t qlen, struct bogu
for (i = ntohs(header->ancount); i != 0; i--)
{
if (name && !extract_name(header, qlen, &p, name, 1, 10))
if (name && !extract_name(header, qlen, &p, name, EXTR_NAME_EXTRACT, 10))
return 0; /* bad packet */
if (!name && !(p = skip_name(p, header, qlen, 10)))
@@ -1629,7 +1644,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
nameoffset = p - (unsigned char *)header;
/* now extract name as .-concatenated string into name */
if (!extract_name(header, qlen, &p, name, 1, 4))
if (!extract_name(header, qlen, &p, name, EXTR_NAME_EXTRACT, 4))
return 0; /* bad packet */
GETSHORT(qtype, p);