mirror of
http://thekelleys.org.uk/git/dnsmasq.git
synced 2026-11-06 15:51:41 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b8f16556d3 | ||
|
|
cbe379ad6b | ||
|
|
338b340be9 | ||
|
|
a006eb7e14 | ||
|
|
554b580e97 | ||
|
|
0df29f5e23 | ||
|
|
b4c0f092d8 | ||
|
|
78c6184752 | ||
|
|
38440b204d |
No files matched your search
@@ -68,18 +68,42 @@ version 2.73
|
|||||||
Fix broken DNSSEC validation of ECDSA signatures.
|
Fix broken DNSSEC validation of ECDSA signatures.
|
||||||
|
|
||||||
Add --dnssec-timestamp option, which provides an automatic
|
Add --dnssec-timestamp option, which provides an automatic
|
||||||
way to detect when the system time becomes valid after boot
|
way to detect when the system time becomes valid after
|
||||||
on systems without an RTC, whilst allowing DNS queries before the
|
boot on systems without an RTC, whilst allowing DNS
|
||||||
clock is valid so that NTP can run. Thanks to
|
queries before the clock is valid so that NTP can run.
|
||||||
Kevin Darbyshire-Bryant for developing this idea.
|
Thanks to Kevin Darbyshire-Bryant for developing this idea.
|
||||||
|
|
||||||
Add --tftp-no-fail option. Thanks to Stefan Tomanek for
|
Add --tftp-no-fail option. Thanks to Stefan Tomanek for
|
||||||
the patch.
|
the patch.
|
||||||
|
|
||||||
Fix crash caused by looking up servers.bind, CHAOS text record,
|
Fix crash caused by looking up servers.bind, CHAOS text
|
||||||
when more than about five --servers= lines are in the dnsmasq
|
record, when more than about five --servers= lines are
|
||||||
config. This causes memory corruption which causes a crash later.
|
in the dnsmasq config. This causes memory corruption
|
||||||
Thanks to Matt Coddington for sterling work chasing this down.
|
which causes a crash later. Thanks to Matt Coddington for
|
||||||
|
sterling work chasing this down.
|
||||||
|
|
||||||
|
Fix crash on receipt of certain malformed DNS requests.
|
||||||
|
Thanks to Nick Sampanis for spotting the problem.
|
||||||
|
Note that this is could allow the dnsmasq process's
|
||||||
|
memory to be read by an attacker under certain
|
||||||
|
circumstances, so it has a CVE, CVE-2015-3294
|
||||||
|
|
||||||
|
Fix crash in authoritative DNS code, if a .arpa zone
|
||||||
|
is declared as authoritative, and then a PTR query which
|
||||||
|
is not to be treated as authoritative arrived. Normally,
|
||||||
|
directly declaring .arpa zone as authoritative is not
|
||||||
|
done, so this crash wouldn't be seen. Instead the
|
||||||
|
relevant .arpa zone should be specified as a subnet
|
||||||
|
in the auth-zone declaration. Thanks to Johnny S. Lee
|
||||||
|
for the bugreport and initial patch.
|
||||||
|
|
||||||
|
Fix authoritative DNS code to correctly reply to NS
|
||||||
|
and SOA queries for .arpa zones for which we are
|
||||||
|
declared authoritative by means of a subnet in auth-zone.
|
||||||
|
Previously we provided correct answers to PTR queries
|
||||||
|
in such zones (including NS and SOA) but not direct
|
||||||
|
NS and SOA queries. Thanks to Johnny S. Lee for
|
||||||
|
pointing out the problem.
|
||||||
|
|
||||||
|
|
||||||
version 2.72
|
version 2.72
|
||||||
@@ -125,9 +149,6 @@ version 2.72
|
|||||||
Fix problem with --local-service option on big-endian platforms
|
Fix problem with --local-service option on big-endian platforms
|
||||||
Thanks to Richard Genoud for the patch.
|
Thanks to Richard Genoud for the patch.
|
||||||
|
|
||||||
Fix crash on receipt of certain malformed DNS requests. Thanks
|
|
||||||
to Nick Sampanis for spotting the problem.
|
|
||||||
|
|
||||||
|
|
||||||
version 2.71
|
version 2.71
|
||||||
Subtle change to error handling to help DNSSEC validation
|
Subtle change to error handling to help DNSSEC validation
|
||||||
|
|||||||
@@ -277,6 +277,11 @@ int main(int argc, char **argv)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (inet_addr(argv[2]) == INADDR_NONE)
|
||||||
|
{
|
||||||
|
perror("invalid ip address");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
lease.s_addr = inet_addr(argv[2]);
|
lease.s_addr = inet_addr(argv[2]);
|
||||||
server = find_interface(lease, nl, if_nametoindex(argv[1]));
|
server = find_interface(lease, nl, if_nametoindex(argv[1]));
|
||||||
|
|||||||
+36
-24
@@ -131,24 +131,27 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qtype == T_PTR)
|
if ((qtype == T_PTR || qtype == T_SOA || qtype == T_NS) &&
|
||||||
|
(flag = in_arpa_name_2_addr(name, &addr)) &&
|
||||||
|
!local_query)
|
||||||
{
|
{
|
||||||
if (!(flag = in_arpa_name_2_addr(name, &addr)))
|
for (zone = daemon->auth_zones; zone; zone = zone->next)
|
||||||
continue;
|
if ((subnet = find_subnet(zone, flag, &addr)))
|
||||||
|
break;
|
||||||
|
|
||||||
if (!local_query)
|
if (!zone)
|
||||||
{
|
{
|
||||||
for (zone = daemon->auth_zones; zone; zone = zone->next)
|
auth = 0;
|
||||||
if ((subnet = find_subnet(zone, flag, &addr)))
|
continue;
|
||||||
break;
|
|
||||||
|
|
||||||
if (!zone)
|
|
||||||
{
|
|
||||||
auth = 0;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else if (qtype == T_SOA)
|
||||||
|
soa = 1, found = 1;
|
||||||
|
else if (qtype == T_NS)
|
||||||
|
ns = 1, found = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qtype == T_PTR && flag)
|
||||||
|
{
|
||||||
intr = NULL;
|
intr = NULL;
|
||||||
|
|
||||||
if (flag == F_IPV4)
|
if (flag == F_IPV4)
|
||||||
@@ -186,7 +189,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
|
|
||||||
if (intr)
|
if (intr)
|
||||||
{
|
{
|
||||||
if (in_zone(zone, intr->name, NULL))
|
if (local_query || in_zone(zone, intr->name, NULL))
|
||||||
{
|
{
|
||||||
found = 1;
|
found = 1;
|
||||||
log_query(flag | F_REVERSE | F_CONFIG, intr->name, &addr, NULL);
|
log_query(flag | F_REVERSE | F_CONFIG, intr->name, &addr, NULL);
|
||||||
@@ -208,8 +211,11 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
*p = 0; /* must be bare name */
|
*p = 0; /* must be bare name */
|
||||||
|
|
||||||
/* add external domain */
|
/* add external domain */
|
||||||
strcat(name, ".");
|
if (zone)
|
||||||
strcat(name, zone->domain);
|
{
|
||||||
|
strcat(name, ".");
|
||||||
|
strcat(name, zone->domain);
|
||||||
|
}
|
||||||
log_query(flag | F_DHCP | F_REVERSE, name, &addr, record_source(crecp->uid));
|
log_query(flag | F_DHCP | F_REVERSE, name, &addr, record_source(crecp->uid));
|
||||||
found = 1;
|
found = 1;
|
||||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
@@ -217,7 +223,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
T_PTR, C_IN, "d", name))
|
T_PTR, C_IN, "d", name))
|
||||||
anscount++;
|
anscount++;
|
||||||
}
|
}
|
||||||
else if (crecp->flags & (F_DHCP | F_HOSTS) && in_zone(zone, name, NULL))
|
else if (crecp->flags & (F_DHCP | F_HOSTS) && (local_query || in_zone(zone, name, NULL)))
|
||||||
{
|
{
|
||||||
log_query(crecp->flags & ~F_FORWARD, name, &addr, record_source(crecp->uid));
|
log_query(crecp->flags & ~F_FORWARD, name, &addr, record_source(crecp->uid));
|
||||||
found = 1;
|
found = 1;
|
||||||
@@ -240,14 +246,20 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
}
|
}
|
||||||
|
|
||||||
cname_restart:
|
cname_restart:
|
||||||
for (zone = daemon->auth_zones; zone; zone = zone->next)
|
if (found)
|
||||||
if (in_zone(zone, name, &cut))
|
/* NS and SOA .arpa requests have set found above. */
|
||||||
break;
|
cut = NULL;
|
||||||
|
else
|
||||||
if (!zone)
|
|
||||||
{
|
{
|
||||||
auth = 0;
|
for (zone = daemon->auth_zones; zone; zone = zone->next)
|
||||||
continue;
|
if (in_zone(zone, name, &cut))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!zone)
|
||||||
|
{
|
||||||
|
auth = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (rec = daemon->mxnames; rec; rec = rec->next)
|
for (rec = daemon->mxnames; rec; rec = rec->next)
|
||||||
|
|||||||
@@ -142,3 +142,11 @@ struct dns_header {
|
|||||||
|
|
||||||
#define ADD_RDLEN(header, pp, plen, len) \
|
#define ADD_RDLEN(header, pp, plen, len) \
|
||||||
(!CHECK_LEN(header, pp, plen, len) ? 0 : (((pp) += (len)), 1))
|
(!CHECK_LEN(header, pp, plen, len) ? 0 : (((pp) += (len)), 1))
|
||||||
|
|
||||||
|
/* Escape character in our presentation format for names.
|
||||||
|
Cannot be '.' or /000 and must be !isprint().
|
||||||
|
Note that escaped chars are stored as
|
||||||
|
<NAME_ESCAPE> <orig-char+1>
|
||||||
|
to ensure that the escaped form of /000 doesn't include /000
|
||||||
|
*/
|
||||||
|
#define NAME_ESCAPE 1
|
||||||
+17
-4
@@ -102,8 +102,19 @@ int main (int argc, char **argv)
|
|||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
if (option_bool(OPT_DNSSEC_VALID))
|
if (option_bool(OPT_DNSSEC_VALID))
|
||||||
{
|
{
|
||||||
daemon->keyname = safe_malloc(MAXDNAME);
|
/* Note that both /000 and '.' are allowed within labels. These get
|
||||||
daemon->workspacename = safe_malloc(MAXDNAME);
|
represented in presentation format using NAME_ESCAPE as an escape
|
||||||
|
character when in DNSSEC mode.
|
||||||
|
In theory, if all the characters in a name were /000 or
|
||||||
|
'.' or NAME_ESCAPE then all would have to be escaped, so the
|
||||||
|
presentation format would be twice as long as the spec.
|
||||||
|
|
||||||
|
daemon->namebuff was previously allocated by the option-reading
|
||||||
|
code before we knew if we're in DNSSEC mode, so reallocate here. */
|
||||||
|
free(daemon->namebuff);
|
||||||
|
daemon->namebuff = safe_malloc(MAXDNAME * 2);
|
||||||
|
daemon->keyname = safe_malloc(MAXDNAME * 2);
|
||||||
|
daemon->workspacename = safe_malloc(MAXDNAME * 2);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -655,7 +666,8 @@ int main (int argc, char **argv)
|
|||||||
_exit(0);
|
_exit(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
closedir(dir);
|
else
|
||||||
|
closedir(dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (p = daemon->if_prefix; p; p = p->next)
|
for (p = daemon->if_prefix; p; p = p->next)
|
||||||
@@ -670,7 +682,8 @@ int main (int argc, char **argv)
|
|||||||
_exit(0);
|
_exit(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
closedir(dir);
|
else
|
||||||
|
closedir(dir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+33
-8
@@ -321,10 +321,18 @@ static int verify(struct blockdata *key_data, unsigned int key_len, unsigned cha
|
|||||||
thus generating names in canonical form.
|
thus generating names in canonical form.
|
||||||
Calling to_wire followed by from_wire is almost an identity,
|
Calling to_wire followed by from_wire is almost an identity,
|
||||||
except that the UC remains mapped to LC.
|
except that the UC remains mapped to LC.
|
||||||
|
|
||||||
|
Note that both /000 and '.' are allowed within labels. These get
|
||||||
|
represented in presentation format using NAME_ESCAPE as an escape
|
||||||
|
character. In theory, if all the characters in a name were /000 or
|
||||||
|
'.' or NAME_ESCAPE then all would have to be escaped, so the
|
||||||
|
presentation format would be twice as long as the spec (1024).
|
||||||
|
The buffers are all delcared as 2049 (allowing for the trailing zero)
|
||||||
|
for this reason.
|
||||||
*/
|
*/
|
||||||
static int to_wire(char *name)
|
static int to_wire(char *name)
|
||||||
{
|
{
|
||||||
unsigned char *l, *p, term;
|
unsigned char *l, *p, *q, term;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
for (l = (unsigned char*)name; *l != 0; l = p)
|
for (l = (unsigned char*)name; *l != 0; l = p)
|
||||||
@@ -332,7 +340,12 @@ static int to_wire(char *name)
|
|||||||
for (p = l; *p != '.' && *p != 0; p++)
|
for (p = l; *p != '.' && *p != 0; p++)
|
||||||
if (*p >= 'A' && *p <= 'Z')
|
if (*p >= 'A' && *p <= 'Z')
|
||||||
*p = *p - 'A' + 'a';
|
*p = *p - 'A' + 'a';
|
||||||
|
else if (*p == NAME_ESCAPE)
|
||||||
|
{
|
||||||
|
for (q = p; *q; q++)
|
||||||
|
*q = *(q+1);
|
||||||
|
(*p)--;
|
||||||
|
}
|
||||||
term = *p;
|
term = *p;
|
||||||
|
|
||||||
if ((len = p - l) != 0)
|
if ((len = p - l) != 0)
|
||||||
@@ -351,13 +364,24 @@ static int to_wire(char *name)
|
|||||||
/* Note: no compression allowed in input. */
|
/* Note: no compression allowed in input. */
|
||||||
static void from_wire(char *name)
|
static void from_wire(char *name)
|
||||||
{
|
{
|
||||||
unsigned char *l;
|
unsigned char *l, *p, *last;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
|
for (last = (unsigned char *)name; *last != 0; last += *last+1);
|
||||||
|
|
||||||
for (l = (unsigned char *)name; *l != 0; l += len+1)
|
for (l = (unsigned char *)name; *l != 0; l += len+1)
|
||||||
{
|
{
|
||||||
len = *l;
|
len = *l;
|
||||||
memmove(l, l+1, len);
|
memmove(l, l+1, len);
|
||||||
|
for (p = l; p < l + len; p++)
|
||||||
|
if (*p == '.' || *p == 0 || *p == NAME_ESCAPE)
|
||||||
|
{
|
||||||
|
memmove(p+1, p, 1 + last - p);
|
||||||
|
len++;
|
||||||
|
*p++ = NAME_ESCAPE;
|
||||||
|
(*p)++;
|
||||||
|
}
|
||||||
|
|
||||||
l[len] = '.';
|
l[len] = '.';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -645,7 +669,7 @@ static void sort_rrset(struct dns_header *header, size_t plen, u16 *rr_desc, int
|
|||||||
if (left1 != 0)
|
if (left1 != 0)
|
||||||
memmove(buff1, buff1 + len1 - left1, left1);
|
memmove(buff1, buff1 + len1 - left1, left1);
|
||||||
|
|
||||||
if ((len1 = get_rdata(header, plen, end1, buff1 + left1, MAXDNAME - left1, &p1, &dp1)) == 0)
|
if ((len1 = get_rdata(header, plen, end1, buff1 + left1, (MAXDNAME * 2) - left1, &p1, &dp1)) == 0)
|
||||||
{
|
{
|
||||||
quit = 1;
|
quit = 1;
|
||||||
len1 = end1 - p1;
|
len1 = end1 - p1;
|
||||||
@@ -656,7 +680,7 @@ static void sort_rrset(struct dns_header *header, size_t plen, u16 *rr_desc, int
|
|||||||
if (left2 != 0)
|
if (left2 != 0)
|
||||||
memmove(buff2, buff2 + len2 - left2, left2);
|
memmove(buff2, buff2 + len2 - left2, left2);
|
||||||
|
|
||||||
if ((len2 = get_rdata(header, plen, end2, buff2 + left2, MAXDNAME - left2, &p2, &dp2)) == 0)
|
if ((len2 = get_rdata(header, plen, end2, buff2 + left2, (MAXDNAME *2) - left2, &p2, &dp2)) == 0)
|
||||||
{
|
{
|
||||||
quit = 1;
|
quit = 1;
|
||||||
len2 = end2 - p2;
|
len2 = end2 - p2;
|
||||||
@@ -902,10 +926,11 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
|
|||||||
|
|
||||||
end = p + rdlen;
|
end = p + rdlen;
|
||||||
|
|
||||||
/* canonicalise rdata and calculate length of same, use name buffer as workspace */
|
/* canonicalise rdata and calculate length of same, use name buffer as workspace.
|
||||||
|
Note that name buffer is twice MAXDNAME long in DNSSEC mode. */
|
||||||
cp = p;
|
cp = p;
|
||||||
dp = rr_desc;
|
dp = rr_desc;
|
||||||
for (len = 0; (seg = get_rdata(header, plen, end, name, MAXDNAME, &cp, &dp)) != 0; len += seg);
|
for (len = 0; (seg = get_rdata(header, plen, end, name, MAXDNAME * 2, &cp, &dp)) != 0; len += seg);
|
||||||
len += end - cp;
|
len += end - cp;
|
||||||
len = htons(len);
|
len = htons(len);
|
||||||
hash->update(ctx, 2, (unsigned char *)&len);
|
hash->update(ctx, 2, (unsigned char *)&len);
|
||||||
@@ -913,7 +938,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
|
|||||||
/* Now canonicalise again and digest. */
|
/* Now canonicalise again and digest. */
|
||||||
cp = p;
|
cp = p;
|
||||||
dp = rr_desc;
|
dp = rr_desc;
|
||||||
while ((seg = get_rdata(header, plen, end, name, MAXDNAME, &cp, &dp)))
|
while ((seg = get_rdata(header, plen, end, name, MAXDNAME * 2, &cp, &dp)))
|
||||||
hash->update(ctx, seg, (unsigned char *)name);
|
hash->update(ctx, seg, (unsigned char *)name);
|
||||||
if (cp != end)
|
if (cp != end)
|
||||||
hash->update(ctx, end - cp, cp);
|
hash->update(ctx, end - cp, cp);
|
||||||
|
|||||||
+9
-4
@@ -1014,7 +1014,7 @@ void reply_query(int fd, int family, time_t now)
|
|||||||
header->hb3 |= HB3_TC;
|
header->hb3 |= HB3_TC;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
char *result;
|
char *result, *domain = "result";
|
||||||
|
|
||||||
if (forward->work_counter == 0)
|
if (forward->work_counter == 0)
|
||||||
{
|
{
|
||||||
@@ -1024,7 +1024,10 @@ void reply_query(int fd, int family, time_t now)
|
|||||||
else
|
else
|
||||||
result = (status == STAT_SECURE ? "SECURE" : (status == STAT_INSECURE ? "INSECURE" : "BOGUS"));
|
result = (status == STAT_SECURE ? "SECURE" : (status == STAT_INSECURE ? "INSECURE" : "BOGUS"));
|
||||||
|
|
||||||
log_query(F_KEYTAG | F_SECSTAT, "result", NULL, result);
|
if (status == STAT_BOGUS && extract_request(header, n, daemon->namebuff, NULL))
|
||||||
|
domain = daemon->namebuff;
|
||||||
|
|
||||||
|
log_query(F_KEYTAG | F_SECSTAT, domain, NULL, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status == STAT_SECURE)
|
if (status == STAT_SECURE)
|
||||||
@@ -1975,7 +1978,7 @@ unsigned char *tcp_request(int confd, time_t now,
|
|||||||
{
|
{
|
||||||
int keycount = DNSSEC_WORK; /* Limit to number of DNSSEC questions, to catch loops and avoid filling cache. */
|
int keycount = DNSSEC_WORK; /* Limit to number of DNSSEC questions, to catch loops and avoid filling cache. */
|
||||||
int status = tcp_key_recurse(now, STAT_TRUNCATED, header, m, 0, daemon->namebuff, daemon->keyname, last_server, &keycount);
|
int status = tcp_key_recurse(now, STAT_TRUNCATED, header, m, 0, daemon->namebuff, daemon->keyname, last_server, &keycount);
|
||||||
char *result;
|
char *result, *domain = "result";
|
||||||
|
|
||||||
if (status == STAT_INSECURE_DS)
|
if (status == STAT_INSECURE_DS)
|
||||||
{
|
{
|
||||||
@@ -1993,8 +1996,10 @@ unsigned char *tcp_request(int confd, time_t now,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
result = (status == STAT_SECURE ? "SECURE" : (status == STAT_INSECURE ? "INSECURE" : "BOGUS"));
|
result = (status == STAT_SECURE ? "SECURE" : (status == STAT_INSECURE ? "INSECURE" : "BOGUS"));
|
||||||
|
if (status == STAT_BOGUS && extract_request(header, m, daemon->namebuff, NULL))
|
||||||
|
domain = daemon->namebuff;
|
||||||
|
|
||||||
log_query(F_KEYTAG | F_SECSTAT, "result", NULL, result);
|
log_query(F_KEYTAG | F_SECSTAT, domain, NULL, result);
|
||||||
|
|
||||||
if (status == STAT_BOGUS)
|
if (status == STAT_BOGUS)
|
||||||
{
|
{
|
||||||
|
|||||||
+29
-4
@@ -20,7 +20,7 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
|
|||||||
char *name, int isExtract, int extrabytes)
|
char *name, int isExtract, int extrabytes)
|
||||||
{
|
{
|
||||||
unsigned char *cp = (unsigned char *)name, *p = *pp, *p1 = NULL;
|
unsigned char *cp = (unsigned char *)name, *p = *pp, *p1 = NULL;
|
||||||
unsigned int j, l, hops = 0;
|
unsigned int j, l, namelen = 0, hops = 0;
|
||||||
int retvalue = 1;
|
int retvalue = 1;
|
||||||
|
|
||||||
if (isExtract)
|
if (isExtract)
|
||||||
@@ -94,9 +94,15 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
|
|||||||
count = 256;
|
count = 256;
|
||||||
digs = ((count-1)>>2)+1;
|
digs = ((count-1)>>2)+1;
|
||||||
|
|
||||||
/* output is \[x<hex>/siz]. which is digs+9 chars */
|
/* output is \[x<hex>/siz]. which is digs+6/7/8 chars */
|
||||||
if (cp - (unsigned char *)name + digs + 9 >= MAXDNAME)
|
namelen += digs+6;
|
||||||
|
if (count > 9)
|
||||||
|
namelen++;
|
||||||
|
if (count > 99)
|
||||||
|
namelen++;
|
||||||
|
if (namelen+1 >= MAXDNAME)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!CHECK_LEN(header, p, plen, (count-1)>>3))
|
if (!CHECK_LEN(header, p, plen, (count-1)>>3))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -119,7 +125,8 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ /* label_type = 0 -> label. */
|
{ /* label_type = 0 -> label. */
|
||||||
if (cp - (unsigned char *)name + l + 1 >= MAXDNAME)
|
namelen += l;
|
||||||
|
if (namelen+1 >= MAXDNAME)
|
||||||
return 0;
|
return 0;
|
||||||
if (!CHECK_LEN(header, p, plen, l))
|
if (!CHECK_LEN(header, p, plen, l))
|
||||||
return 0;
|
return 0;
|
||||||
@@ -128,6 +135,19 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
|
|||||||
if (isExtract)
|
if (isExtract)
|
||||||
{
|
{
|
||||||
unsigned char c = *p;
|
unsigned char c = *p;
|
||||||
|
#ifdef HAVE_DNSSEC
|
||||||
|
if (option_bool(OPT_DNSSEC_VALID))
|
||||||
|
{
|
||||||
|
if (c == 0 || c == '.' || c == NAME_ESCAPE)
|
||||||
|
{
|
||||||
|
*cp++ = NAME_ESCAPE;
|
||||||
|
*cp++ = c+1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*cp++ = c;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
if (c != 0 && c != '.')
|
if (c != 0 && c != '.')
|
||||||
*cp++ = c;
|
*cp++ = c;
|
||||||
else
|
else
|
||||||
@@ -144,6 +164,11 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
|
|||||||
cp++;
|
cp++;
|
||||||
if (c1 >= 'A' && c1 <= 'Z')
|
if (c1 >= 'A' && c1 <= 'Z')
|
||||||
c1 += 'a' - 'A';
|
c1 += 'a' - 'A';
|
||||||
|
#ifdef HAVE_DNSSEC
|
||||||
|
if (option_bool(OPT_DNSSEC_VALID) && c1 == NAME_ESCAPE)
|
||||||
|
c1 = (*cp++)-1;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (c2 >= 'A' && c2 <= 'Z')
|
if (c2 >= 'A' && c2 <= 'Z')
|
||||||
c2 += 'a' - 'A';
|
c2 += 'a' - 'A';
|
||||||
|
|
||||||
|
|||||||
+10
-14
@@ -824,25 +824,21 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Windows 8 always requests an address even if the Managed bit
|
|
||||||
in RA is 0 and it keeps retrying if it receives a reply
|
|
||||||
stating that no addresses are available. We solve this
|
|
||||||
by not replying at all if we're not configured to give any
|
|
||||||
addresses by DHCPv6. RFC 3315 17.2.1. appears to allow this. */
|
|
||||||
|
|
||||||
for (c = state->context; c; c = c->current)
|
|
||||||
if (!(c->flags & CONTEXT_RA_STATELESS))
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (!c)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* no address, return error */
|
/* no address, return error */
|
||||||
o1 = new_opt6(OPTION6_STATUS_CODE);
|
o1 = new_opt6(OPTION6_STATUS_CODE);
|
||||||
put_opt6_short(DHCP6NOADDRS);
|
put_opt6_short(DHCP6NOADDRS);
|
||||||
put_opt6_string(_("no addresses available"));
|
put_opt6_string(_("no addresses available"));
|
||||||
end_opt6(o1);
|
end_opt6(o1);
|
||||||
log6_packet(state, state->lease_allocate ? "DHCPREPLY" : "DHCPADVERTISE", NULL, _("no addresses available"));
|
|
||||||
|
/* Some clients will ask repeatedly when we're not giving
|
||||||
|
out addresses because we're in stateless mode. Avoid spamming
|
||||||
|
the log in that case. */
|
||||||
|
for (c = state->context; c; c = c->current)
|
||||||
|
if (!(c->flags & CONTEXT_RA_STATELESS))
|
||||||
|
{
|
||||||
|
log6_packet(state, state->lease_allocate ? "DHCPREPLY" : "DHCPADVERTISE", NULL, _("no addresses available"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|||||||
+8
-1
@@ -226,7 +226,14 @@ unsigned char *do_rfc1035_name(unsigned char *p, char *sval)
|
|||||||
{
|
{
|
||||||
unsigned char *cp = p++;
|
unsigned char *cp = p++;
|
||||||
for (j = 0; *sval && (*sval != '.'); sval++, j++)
|
for (j = 0; *sval && (*sval != '.'); sval++, j++)
|
||||||
*p++ = *sval;
|
{
|
||||||
|
#ifdef HAVE_DNSSEC
|
||||||
|
if (option_bool(OPT_DNSSEC_VALID) && *sval == NAME_ESCAPE)
|
||||||
|
*p++ = (*(++sval))-1;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
*p++ = *sval;
|
||||||
|
}
|
||||||
*cp = j;
|
*cp = j;
|
||||||
if (*sval)
|
if (*sval)
|
||||||
sval++;
|
sval++;
|
||||||
|
|||||||
Reference in new issue
Block a user