#ifdef HAVE_DNSSEC
if (option_bool(OPT_DNSSEC_VALID))
{
- daemon->keyname = safe_malloc(MAXDNAME);
- daemon->workspacename = safe_malloc(MAXDNAME);
+ /* Note that both /000 and '.' are allowed within labels. These get
+ 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
thus generating names in canonical form.
Calling to_wire followed by from_wire is almost an identity,
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)
{
- unsigned char *l, *p, term;
+ unsigned char *l, *p, *q, term;
int len;
for (l = (unsigned char*)name; *l != 0; l = p)
for (p = l; *p != '.' && *p != 0; p++)
if (*p >= 'A' && *p <= 'Z')
*p = *p - 'A' + 'a';
-
+ else if (*p == NAME_ESCAPE)
+ for (q = p; *q; q++)
+ *q = *(q+1);
+
term = *p;
if ((len = p - l) != 0)
/* Note: no compression allowed in input. */
static void from_wire(char *name)
{
- unsigned char *l;
+ unsigned char *l, *p, *last;
int len;
-
+
+ for (last = (unsigned char *)name; *last != 0; last += *last+1);
+
for (l = (unsigned char *)name; *l != 0; l += len+1)
{
len = *l;
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;
+ }
+
l[len] = '.';
}
if (left1 != 0)
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;
len1 = end1 - p1;
if (left2 != 0)
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;
len2 = end2 - p2;
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;
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 = htons(len);
hash->update(ctx, 2, (unsigned char *)&len);
/* Now canonicalise again and digest. */
cp = p;
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);
if (cp != end)
hash->update(ctx, end - cp, cp);