mirror of
http://thekelleys.org.uk/git/dnsmasq.git
synced 2026-11-13 17:00:49 +00:00
Compare commits
5
Commits
v2.91test8
...
v2.91test9
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a4569c22cc | ||
|
|
199e65c4d9 | ||
|
|
bb8811d472 | ||
|
|
995a16ca0c | ||
|
|
65f9c1aca1 |
No files matched your search
@@ -97,6 +97,20 @@ version 2.91
|
|||||||
queries to dnsmasq acting as forwarder for a zone for which it is
|
queries to dnsmasq acting as forwarder for a zone for which it is
|
||||||
authoritative.
|
authoritative.
|
||||||
|
|
||||||
|
Implement "DNS-0x20 encoding", for 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.
|
||||||
|
|
||||||
|
|
||||||
version 2.90
|
version 2.90
|
||||||
Fix reversion in --rev-server introduced in 2.88 which
|
Fix reversion in --rev-server introduced in 2.88 which
|
||||||
|
|||||||
+1
-1
@@ -882,7 +882,7 @@ ie capable of returning DNSSEC records with data. If they are not,
|
|||||||
then dnsmasq will not be able to determine the trusted status of
|
then dnsmasq will not be able to determine the trusted status of
|
||||||
answers and this means that DNS service will be entirely broken.
|
answers and this means that DNS service will be entirely broken.
|
||||||
.TP
|
.TP
|
||||||
.B --trust-anchor=[<class>],<domain>,<key-tag>,<algorithm>,<digest-type>,<digest>
|
.B --trust-anchor=<domain>,[<class>,]<key-tag>,<algorithm>,<digest-type>,<digest>
|
||||||
Provide DS records to act a trust anchors for DNSSEC
|
Provide DS records to act a trust anchors for DNSSEC
|
||||||
validation. Typically these will be the DS record(s) for Key Signing
|
validation. Typically these will be the DS record(s) for Key Signing
|
||||||
key(s) (KSK) of the root zone,
|
key(s) (KSK) of the root zone,
|
||||||
|
|||||||
+1
-1
@@ -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;
|
nameoffset = p - (unsigned char *)header;
|
||||||
|
|
||||||
/* now extract name as .-concatenated string into name */
|
/* 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 */
|
return 0; /* bad packet */
|
||||||
|
|
||||||
GETSHORT(qtype, p);
|
GETSHORT(qtype, p);
|
||||||
|
|||||||
+19
-3
@@ -1852,14 +1852,30 @@ int cache_make_stat(struct txt_record *t)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* There can be names in the cache containing control chars, don't
|
/* There can be names in the cache containing control chars, don't
|
||||||
mess up logging or open security holes. */
|
mess up logging or open security holes. Also convert to all-LC
|
||||||
|
so that 0x20-encoding doesn't make logs look like ransom notes
|
||||||
|
made out of letters cut from a newspaper.
|
||||||
|
Overwrites daemon->workspacename */
|
||||||
static char *sanitise(char *name)
|
static char *sanitise(char *name)
|
||||||
{
|
{
|
||||||
unsigned char *r;
|
unsigned char *r = (unsigned char *)name;
|
||||||
|
|
||||||
if (name)
|
if (name)
|
||||||
for (r = (unsigned char *)name; *r; r++)
|
{
|
||||||
|
char *d = name = daemon->workspacename;
|
||||||
|
|
||||||
|
for (; *r; r++, d++)
|
||||||
if (!isprint((int)*r))
|
if (!isprint((int)*r))
|
||||||
return "<name unprintable>";
|
return "<name unprintable>";
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned char c = *r;
|
||||||
|
|
||||||
|
*d = (char)((c >= 'A' && c <= 'Z') ? c + 'a' - 'A' : c);
|
||||||
|
}
|
||||||
|
|
||||||
|
*d = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-1
@@ -790,6 +790,7 @@ struct frec {
|
|||||||
int forwardall, flags;
|
int forwardall, flags;
|
||||||
time_t time;
|
time_t time;
|
||||||
u32 forward_timestamp;
|
u32 forward_timestamp;
|
||||||
|
unsigned int encode_bitmap;
|
||||||
int forward_delay;
|
int forward_delay;
|
||||||
struct blockdata *stash; /* saved query or saved reply, whilst we validate */
|
struct blockdata *stash; /* saved query or saved reply, whilst we validate */
|
||||||
size_t stash_len;
|
size_t stash_len;
|
||||||
@@ -1386,7 +1387,7 @@ int is_rev_synth(int flag, union all_addr *addr, char *name);
|
|||||||
/* rfc1035.c */
|
/* rfc1035.c */
|
||||||
int do_doctor(struct dns_header *header, size_t qlen, char *namebuff);
|
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,
|
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_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_questions(struct dns_header *header, size_t plen);
|
||||||
unsigned char *skip_section(unsigned char *ansp, int count, 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 *offset, unsigned short type, unsigned short class, char *format, ...);
|
||||||
int in_arpa_name_2_addr(char *namein, union all_addr *addrp);
|
int in_arpa_name_2_addr(char *namein, union all_addr *addrp);
|
||||||
int private_net(struct in_addr addr, int ban_localhost);
|
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 */
|
/* auth.c */
|
||||||
#ifdef HAVE_AUTH
|
#ifdef HAVE_AUTH
|
||||||
|
|||||||
+23
-23
@@ -191,7 +191,7 @@ static int get_rdata(struct dns_header *header, size_t plen, struct rdata_state
|
|||||||
/* domain-name, canonicalise */
|
/* domain-name, canonicalise */
|
||||||
int len;
|
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)
|
(len = to_wire(state->buff)) == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -339,7 +339,7 @@ static int explore_rrset(struct dns_header *header, size_t plen, int class, int
|
|||||||
|
|
||||||
pstart = p;
|
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 */
|
return 0; /* bad packet */
|
||||||
|
|
||||||
GETSHORT(stype, p);
|
GETSHORT(stype, p);
|
||||||
@@ -374,14 +374,14 @@ static int explore_rrset(struct dns_header *header, size_t plen, int class, int
|
|||||||
if (gotkey)
|
if (gotkey)
|
||||||
{
|
{
|
||||||
/* If there's more than one SIG, ensure they all have same keyname */
|
/* 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;
|
return 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
gotkey = 1;
|
gotkey = 1;
|
||||||
|
|
||||||
if (!extract_name(header, plen, &p, keyname, 1, 0))
|
if (!extract_name(header, plen, &p, keyname, EXTR_NAME_EXTRACT, 0))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* RFC 4035 5.3.1 says that the Signer's Name field MUST equal
|
/* 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);
|
GETLONG(sig_inception, p);
|
||||||
GETSHORT(key_tag, 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;
|
return STAT_BOGUS;
|
||||||
|
|
||||||
if (!time_check)
|
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];
|
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;
|
return STAT_BOGUS;
|
||||||
|
|
||||||
name_start = name;
|
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 */
|
/* namebuff used for workspace above, restore to leave unchanged on exit */
|
||||||
p = (unsigned char*)(rrset[0]);
|
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;
|
return STAT_BOGUS;
|
||||||
|
|
||||||
if (key)
|
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 unsigned char **cached_digest;
|
||||||
static size_t cached_digest_size = 0;
|
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;
|
return STAT_BOGUS | DNSSEC_FAIL_NOKEY;
|
||||||
|
|
||||||
GETSHORT(qtype, p);
|
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--)
|
for (j = ntohs(header->ancount); j != 0; j--)
|
||||||
{
|
{
|
||||||
/* Ensure we have type, class TTL and length */
|
/* 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 */
|
return STAT_BOGUS; /* bad packet */
|
||||||
|
|
||||||
GETSHORT(qtype, p);
|
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--)
|
for (j = ntohs(header->ancount); j != 0; j--)
|
||||||
{
|
{
|
||||||
/* Ensure we have type, class TTL and length */
|
/* 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 */
|
return STAT_BOGUS; /* bad packet */
|
||||||
|
|
||||||
GETSHORT(qtype, p);
|
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);
|
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;
|
return STAT_BOGUS;
|
||||||
|
|
||||||
p += 4; /* qtype, qclass */
|
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;
|
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 */
|
return STAT_BOGUS; /* bad packet */
|
||||||
|
|
||||||
GETSHORT(atype, p);
|
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;
|
int sig_labels, name_labels;
|
||||||
|
|
||||||
p = nsecs[i];
|
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;
|
return DNSSEC_FAIL_BADPACKET;
|
||||||
p += 8; /* class, type, TTL */
|
p += 8; /* class, type, TTL */
|
||||||
GETSHORT(rdlen, p);
|
GETSHORT(rdlen, p);
|
||||||
psave = 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;
|
return DNSSEC_FAIL_BADPACKET;
|
||||||
|
|
||||||
/* If NSEC comes from wildcard expansion, use original wildcard
|
/* 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++)
|
for (i = 0; i < nsec_count; i++)
|
||||||
if ((p = nsecs[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)))
|
!(base32_len = base32_decode(workspace1, (unsigned char *)workspace2)))
|
||||||
return 0;
|
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++)
|
for (i = 0; i < nsec_count; i++)
|
||||||
if ((p = nsecs[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;
|
return DNSSEC_FAIL_BADPACKET;
|
||||||
|
|
||||||
if (!(base32_len = base32_decode(workspace1, (unsigned char *)workspace2)))
|
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;
|
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;
|
return DNSSEC_FAIL_BADPACKET;
|
||||||
|
|
||||||
GETSHORT(type, p);
|
GETSHORT(type, p);
|
||||||
@@ -1735,7 +1735,7 @@ static int prove_non_existence(struct dns_header *header, size_t plen, char *key
|
|||||||
{
|
{
|
||||||
unsigned char *psav;
|
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;
|
return DNSSEC_FAIL_BADPACKET;
|
||||||
|
|
||||||
GETSHORT(type1, p1);
|
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;
|
targets[0] = p1;
|
||||||
targetidx = 1;
|
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;
|
return STAT_BOGUS;
|
||||||
|
|
||||||
GETSHORT(qtype, p1);
|
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))
|
if (i != 0 && !ADD_RDLEN(header, p1, plen, rdlen1))
|
||||||
return STAT_BOGUS;
|
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 */
|
return STAT_BOGUS; /* bad packet */
|
||||||
|
|
||||||
GETSHORT(type1, p1);
|
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 */
|
/* Check if we've done this RRset already */
|
||||||
for (p2 = ans_start, j = 0; j < i; j++)
|
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 */
|
return STAT_BOGUS; /* bad packet */
|
||||||
|
|
||||||
GETSHORT(type2, p2);
|
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]))
|
if ((p2 = targets[j]))
|
||||||
{
|
{
|
||||||
int rc1;
|
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 */
|
return STAT_BOGUS; /* bad packet */
|
||||||
|
|
||||||
if (class1 == qclass && rc1 == 1 && (type1 == T_CNAME || type1 == qtype || qtype == T_ANY ))
|
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)
|
if (neganswer)
|
||||||
*neganswer = 1;
|
*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 */
|
return STAT_BOGUS; /* bad packet */
|
||||||
|
|
||||||
/* NXDOMAIN or NODATA reply, unanswered question is (name, qclass, qtype) */
|
/* NXDOMAIN or NODATA reply, unanswered question is (name, qclass, qtype) */
|
||||||
|
|||||||
+18
-5
@@ -264,6 +264,8 @@ static void forward_query(int udpfd, union mysockaddr *udpaddr,
|
|||||||
/* new query */
|
/* new query */
|
||||||
if (!forward)
|
if (!forward)
|
||||||
{
|
{
|
||||||
|
unsigned char *p;
|
||||||
|
|
||||||
if (OPCODE(header) != QUERY)
|
if (OPCODE(header) != QUERY)
|
||||||
{
|
{
|
||||||
flags = F_RCODE;
|
flags = F_RCODE;
|
||||||
@@ -324,6 +326,11 @@ static void forward_query(int udpfd, union mysockaddr *udpaddr,
|
|||||||
forward->new_id = get_id();
|
forward->new_id = get_id();
|
||||||
header->id = ntohs(forward->new_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 */
|
/* Keep copy of query for retries and move to TCP */
|
||||||
if (!(forward->stash = blockdata_alloc((char *)header, plen)))
|
if (!(forward->stash = blockdata_alloc((char *)header, plen)))
|
||||||
{
|
{
|
||||||
@@ -968,6 +975,7 @@ static void dnssec_validate(struct frec *forward, struct dns_header *header,
|
|||||||
new->flags &= ~(FREC_DNSKEY_QUERY | FREC_DS_QUERY);
|
new->flags &= ~(FREC_DNSKEY_QUERY | FREC_DS_QUERY);
|
||||||
new->flags |= flags;
|
new->flags |= flags;
|
||||||
new->forwardall = 0;
|
new->forwardall = 0;
|
||||||
|
new->encode_bitmap = 0;
|
||||||
|
|
||||||
forward->next_dependent = NULL;
|
forward->next_dependent = NULL;
|
||||||
new->dependent = forward; /* to find query awaiting new one. */
|
new->dependent = forward; /* to find query awaiting new one. */
|
||||||
@@ -1085,7 +1093,7 @@ void reply_query(int fd, time_t now)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
p = (unsigned char *)(header+1);
|
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 */
|
return; /* bad packet */
|
||||||
GETSHORT(rrtype, p);
|
GETSHORT(rrtype, p);
|
||||||
GETSHORT(class, p);
|
GETSHORT(class, p);
|
||||||
@@ -1195,6 +1203,10 @@ void reply_query(int fd, time_t now)
|
|||||||
/* denominator controls how many queries we average over. */
|
/* denominator controls how many queries we average over. */
|
||||||
server->query_latency = server->mma_latency/128;
|
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
|
#ifdef HAVE_DNSSEC
|
||||||
if (option_bool(OPT_DNSSEC_VALID))
|
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. */
|
/* Save the query to make sure we get the answer we expect. */
|
||||||
p = (unsigned char *)(header+1);
|
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;
|
return 0;
|
||||||
GETSHORT(type, p);
|
GETSHORT(type, p);
|
||||||
GETSHORT(class, p);
|
GETSHORT(class, p);
|
||||||
@@ -1999,12 +2011,12 @@ static ssize_t tcp_talk(int first, int last, int start, unsigned char *packet,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the question section of the reply doesn't match the crc we sent, then
|
/* If the question section of the reply doesn't match the question we sent, then
|
||||||
someone might be attempting to insert bogus values into the cache by
|
someone might be attempting to insert bogus values into the cache by
|
||||||
sending replies containing questions and bogus answers.
|
sending replies containing questions and bogus answers.
|
||||||
Try another server, or give up */
|
Try another server, or give up */
|
||||||
p = (unsigned char *)(header+1);
|
p = (unsigned char *)(header+1);
|
||||||
if (extract_name(header, rsize, &p, daemon->namebuff, 0, 4) != 1)
|
if (extract_name(header, rsize, &p, daemon->namebuff, EXTR_NAME_NOCASE, 4) != 1)
|
||||||
continue;
|
continue;
|
||||||
GETSHORT(rtype, p);
|
GETSHORT(rtype, p);
|
||||||
GETSHORT(rclass, p);
|
GETSHORT(rclass, p);
|
||||||
@@ -3046,7 +3058,8 @@ static struct frec *lookup_frec(char *target, int class, int rrtype, int id, int
|
|||||||
unsigned char *p = (unsigned char *)(header+1);
|
unsigned char *p = (unsigned char *)(header+1);
|
||||||
int hclass, hrrtype;
|
int hclass, hrrtype;
|
||||||
|
|
||||||
if (extract_name(header, f->stash_len, &p, target, 0, 4) != 1)
|
/* Case sensitive compare for DNS-0x20 encoding. */
|
||||||
|
if (extract_name(header, f->stash_len, &p, target, EXTR_NAME_NOCASE, 4) != 1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
GETSHORT(hrrtype, p);
|
GETSHORT(hrrtype, p);
|
||||||
|
|||||||
+1
-1
@@ -568,7 +568,7 @@ static struct {
|
|||||||
{ LOPT_CMARK_ALST, ARG_DUP, "<connmark>[/<mask>][,<pattern>[/<pattern>...]]", gettext_noop("Set allowed DNS patterns for a connection-track mark."), NULL },
|
{ LOPT_CMARK_ALST, ARG_DUP, "<connmark>[/<mask>][,<pattern>[/<pattern>...]]", gettext_noop("Set allowed DNS patterns for a connection-track mark."), NULL },
|
||||||
{ LOPT_SYNTH, ARG_DUP, "<domain>,<range>,[<prefix>]", gettext_noop("Specify a domain and address range for synthesised names"), NULL },
|
{ LOPT_SYNTH, ARG_DUP, "<domain>,<range>,[<prefix>]", gettext_noop("Specify a domain and address range for synthesised names"), NULL },
|
||||||
{ LOPT_SEC_VALID, OPT_DNSSEC_VALID, NULL, gettext_noop("Activate DNSSEC validation"), NULL },
|
{ LOPT_SEC_VALID, OPT_DNSSEC_VALID, NULL, gettext_noop("Activate DNSSEC validation"), NULL },
|
||||||
{ LOPT_TRUST_ANCHOR, ARG_DUP, "<domain>,[<class>],...", gettext_noop("Specify trust anchor key digest."), NULL },
|
{ LOPT_TRUST_ANCHOR, ARG_DUP, "<domain>,[<class>,]...", gettext_noop("Specify trust anchor key digest."), NULL },
|
||||||
{ LOPT_DNSSEC_DEBUG, OPT_DNSSEC_DEBUG, NULL, gettext_noop("Disable upstream checking for DNSSEC debugging."), NULL },
|
{ LOPT_DNSSEC_DEBUG, OPT_DNSSEC_DEBUG, NULL, gettext_noop("Disable upstream checking for DNSSEC debugging."), NULL },
|
||||||
{ LOPT_DNSSEC_CHECK, ARG_DUP, NULL, gettext_noop("Ensure answers without DNSSEC are in unsigned zones."), NULL },
|
{ LOPT_DNSSEC_CHECK, ARG_DUP, NULL, gettext_noop("Ensure answers without DNSSEC are in unsigned zones."), NULL },
|
||||||
{ LOPT_DNSSEC_TIME, OPT_DNSSEC_TIME, NULL, gettext_noop("Don't check DNSSEC signature timestamps until first cache-reload"), NULL },
|
{ LOPT_DNSSEC_TIME, OPT_DNSSEC_TIME, NULL, gettext_noop("Don't check DNSSEC signature timestamps until first cache-reload"), NULL },
|
||||||
|
|||||||
+50
-25
@@ -16,15 +16,28 @@
|
|||||||
|
|
||||||
#include "dnsmasq.h"
|
#include "dnsmasq.h"
|
||||||
|
|
||||||
|
/* 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, flip OK
|
||||||
|
return = 2 -> extract OK, compare failed.
|
||||||
|
*/
|
||||||
int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
|
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 char *cp = (unsigned char *)name, *p = *pp, *p1 = NULL;
|
||||||
unsigned int j, l, namelen = 0, hops = 0;
|
unsigned int j, l, namelen = 0, hops = 0;
|
||||||
int retvalue = 1;
|
int retvalue = 1, case_insens = 1, isExtract = 0, flip = 0, extrabytes = (int)parm;
|
||||||
|
|
||||||
if (isExtract)
|
if (func == EXTR_NAME_EXTRACT)
|
||||||
*cp = 0;
|
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)
|
while (1)
|
||||||
{
|
{
|
||||||
@@ -46,7 +59,7 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
|
|||||||
cp--;
|
cp--;
|
||||||
*cp = 0; /* terminate: lose final period */
|
*cp = 0; /* terminate: lose final period */
|
||||||
}
|
}
|
||||||
else if (*cp != 0)
|
else if (!flip && *cp != 0)
|
||||||
retvalue = 2;
|
retvalue = 2;
|
||||||
|
|
||||||
if (p1) /* we jumped via compression */
|
if (p1) /* we jumped via compression */
|
||||||
@@ -85,7 +98,7 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
|
|||||||
if (!CHECK_LEN(header, p, plen, l))
|
if (!CHECK_LEN(header, p, plen, l))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
for(j=0; j<l; j++, p++)
|
for (j=0; j<l; j++, p++)
|
||||||
if (isExtract)
|
if (isExtract)
|
||||||
{
|
{
|
||||||
unsigned char c = *p;
|
unsigned char c = *p;
|
||||||
@@ -98,6 +111,18 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
|
|||||||
else
|
else
|
||||||
*cp++ = c;
|
*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
|
else
|
||||||
{
|
{
|
||||||
unsigned char c1 = *cp, c2 = *p;
|
unsigned char c1 = *cp, c2 = *p;
|
||||||
@@ -107,13 +132,13 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
cp++;
|
cp++;
|
||||||
if (c1 >= 'A' && c1 <= 'Z')
|
|
||||||
c1 += 'a' - 'A';
|
|
||||||
|
|
||||||
if (c1 == NAME_ESCAPE)
|
if (c1 == NAME_ESCAPE)
|
||||||
c1 = (*cp++)-1;
|
c1 = (*cp++)-1;
|
||||||
|
else if (case_insens && c1 >= 'A' && c1 <= 'Z')
|
||||||
|
c1 += 'a' - 'A';
|
||||||
|
|
||||||
if (c2 >= 'A' && c2 <= 'Z')
|
if (case_insens && c2 >= 'A' && c2 <= 'Z')
|
||||||
c2 += 'a' - 'A';
|
c2 += 'a' - 'A';
|
||||||
|
|
||||||
if (c1 != c2)
|
if (c1 != c2)
|
||||||
@@ -123,7 +148,7 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
|
|||||||
|
|
||||||
if (isExtract)
|
if (isExtract)
|
||||||
*cp++ = '.';
|
*cp++ = '.';
|
||||||
else if (*cp != 0 && *cp++ != '.')
|
else if (!flip && *cp != 0 && *cp++ != '.')
|
||||||
retvalue = 2;
|
retvalue = 2;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -399,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)))
|
if (i == ntohs(header->ancount) && !(p = skip_section(p, ntohs(header->nscount), header, qlen)))
|
||||||
return done;
|
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 */
|
return done; /* bad packet */
|
||||||
|
|
||||||
GETSHORT(qtype, p);
|
GETSHORT(qtype, p);
|
||||||
@@ -480,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++)
|
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 */
|
return 0; /* bad packet */
|
||||||
|
|
||||||
GETSHORT(qtype, p);
|
GETSHORT(qtype, p);
|
||||||
@@ -509,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 */
|
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)
|
if (!no_cache)
|
||||||
blockdata_free(addr.rrblock.rrdata);
|
blockdata_free(addr.rrblock.rrdata);
|
||||||
@@ -660,7 +685,7 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
|
|
||||||
namep = p = (unsigned char *)(header+1);
|
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 */
|
return 2; /* bad packet */
|
||||||
|
|
||||||
GETSHORT(qtype, p);
|
GETSHORT(qtype, p);
|
||||||
@@ -684,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++)
|
for (j = 0; j < ntohs(header->ancount); j++)
|
||||||
{
|
{
|
||||||
int secflag = 0;
|
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 */
|
return 2; /* bad packet */
|
||||||
|
|
||||||
GETSHORT(aqtype, p1);
|
GETSHORT(aqtype, p1);
|
||||||
@@ -722,7 +747,7 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
if (aqtype == T_CNAME)
|
if (aqtype == T_CNAME)
|
||||||
log_query(secflag | F_CNAME | F_FORWARD | F_UPSTREAM, name, NULL, NULL, 0);
|
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;
|
return 2;
|
||||||
|
|
||||||
if (aqtype == T_CNAME)
|
if (aqtype == T_CNAME)
|
||||||
@@ -800,7 +825,7 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
{
|
{
|
||||||
int secflag = 0;
|
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 */
|
return 2; /* bad packet */
|
||||||
|
|
||||||
GETSHORT(aqtype, p1);
|
GETSHORT(aqtype, p1);
|
||||||
@@ -862,7 +887,7 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
}
|
}
|
||||||
|
|
||||||
namep = p1;
|
namep = p1;
|
||||||
if (!extract_name(header, qlen, &p1, name, 1, 0))
|
if (!extract_name(header, qlen, &p1, name, EXTR_NAME_EXTRACT, 0))
|
||||||
return 2;
|
return 2;
|
||||||
|
|
||||||
if (qtype != T_CNAME)
|
if (qtype != T_CNAME)
|
||||||
@@ -932,7 +957,7 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
/* Name, extract it then re-encode. */
|
/* Name, extract it then re-encode. */
|
||||||
int len;
|
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);
|
blockdata_free(addr.rrblock.rrdata);
|
||||||
return 2;
|
return 2;
|
||||||
@@ -965,7 +990,7 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
} while (desc != -1);
|
} while (desc != -1);
|
||||||
|
|
||||||
/* we overwrote the original name, so get it back here. */
|
/* 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);
|
blockdata_free(addr.rrblock.rrdata);
|
||||||
return 2;
|
return 2;
|
||||||
@@ -1127,7 +1152,7 @@ void report_addresses(struct dns_header *header, size_t len, u32 mark)
|
|||||||
{
|
{
|
||||||
int aqtype, aqclass, ardlen;
|
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;
|
return;
|
||||||
|
|
||||||
if (!CHECK_LEN(header, p, len, 10))
|
if (!CHECK_LEN(header, p, len, 10))
|
||||||
@@ -1145,7 +1170,7 @@ void report_addresses(struct dns_header *header, size_t len, u32 mark)
|
|||||||
{
|
{
|
||||||
if (aqtype == T_CNAME)
|
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;
|
return;
|
||||||
if (safe_name(daemon->namebuff) && safe_name(daemon->workspacename))
|
if (safe_name(daemon->namebuff) && safe_name(daemon->workspacename))
|
||||||
ubus_event_bcast_connmark_allowlist_resolved(mark, daemon->namebuff, daemon->workspacename, attl);
|
ubus_event_bcast_connmark_allowlist_resolved(mark, daemon->namebuff, daemon->workspacename, attl);
|
||||||
@@ -1195,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))
|
if (!(header->hb3 & HB3_QR) && (ntohs(header->ancount) != 0 || ntohs(header->nscount) != 0))
|
||||||
return 0; /* non-standard query. */
|
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 */
|
return 0; /* bad packet */
|
||||||
|
|
||||||
GETSHORT(qtype, p);
|
GETSHORT(qtype, p);
|
||||||
@@ -1309,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--)
|
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 */
|
return 0; /* bad packet */
|
||||||
|
|
||||||
if (!name && !(p = skip_name(p, header, qlen, 10)))
|
if (!name && !(p = skip_name(p, header, qlen, 10)))
|
||||||
@@ -1619,7 +1644,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
nameoffset = p - (unsigned char *)header;
|
nameoffset = p - (unsigned char *)header;
|
||||||
|
|
||||||
/* now extract name as .-concatenated string into name */
|
/* 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 */
|
return 0; /* bad packet */
|
||||||
|
|
||||||
GETSHORT(qtype, p);
|
GETSHORT(qtype, p);
|
||||||
|
|||||||
Reference in new issue
Block a user