diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/options.c | 85 | ||||
-rw-r--r-- | common/parse.c | 52 |
2 files changed, 126 insertions, 11 deletions
diff --git a/common/options.c b/common/options.c index 5b4f17d9..09723c60 100644 --- a/common/options.c +++ b/common/options.c @@ -35,6 +35,8 @@ struct option *vendor_cfg_option; static int pretty_text(char **, char *, const unsigned char **, const unsigned char *, int); +static int pretty_dname(char **, char *, const unsigned char *, + const unsigned char *); static int pretty_domain(char **, char *, const unsigned char **, const unsigned char *); static int prepare_option_buffer(struct universe *universe, struct buffer *bp, @@ -1601,7 +1603,6 @@ format_has_text(format) p = format; while (*p != '\0') { switch (*p++) { - case 'd': case 't': return 1; @@ -1615,6 +1616,7 @@ format_has_text(format) case 'X': case 'x': case 'D': + case 'd': return 0; case 'c': @@ -1857,8 +1859,23 @@ const char *pretty_print_option (option, data, len, emit_commas, emit_quotes) numhunk = -2; break; case 'd': - fmtbuf[l] = 't'; - /* Fall Through ! */ + /* Should not be optional, array or compressed */ + if ((option->format[i+1] == 'o') || + (option->format[i+1] == 'a') || + (option->format[i+1] == 'A') || + (option->format[i+1] == 'c')) { + log_error("%s: Illegal use of domain name: %s", + option->name, + &(option->format[i-1])); + fmtbuf[l + 1] = 0; + } + k = MRns_name_len(data + len, data + hunksize); + if (k == -1) { + log_error("Invalid domain name."); + return "<error>"; + } + hunksize += k; + break; case 't': fmtbuf[l + 1] = 0; numhunk = -2; @@ -2012,6 +2029,18 @@ const char *pretty_print_option (option, data, len, emit_commas, emit_quotes) } *op = 0; break; + case 'd': /* RFC1035 format name */ + k = MRns_name_len(data + len, dp); + /* Already tested... */ + if (k == -1) { + log_error("invalid domain name."); + return "<error>"; + } + pretty_dname(&op, endbuf-1, dp, data + len); + /* pretty_dname does not add the nul */ + *op = '\0'; + dp += k; + break; case 'D': /* RFC1035 format name list */ for( ; dp < (data + len) ; dp += k) { unsigned char nbuff[NS_MAXCDNAME]; @@ -4184,6 +4213,56 @@ pretty_text(char **dst, char *dend, const unsigned char **src, } static int +pretty_dname(char **dst, char *dend, const unsigned char *src, + const unsigned char *send) +{ + const unsigned char *tend; + const unsigned char *srcp = src; + int count = 0; + int tsiz, status; + + if (dst == NULL || dend == NULL || src == NULL || send == NULL || + *dst == NULL || ((*dst + 1) > dend) || (src >= send)) + return -1; + + do { + /* Continue loop until end of src buffer. */ + if (srcp >= send) + break; + + /* Consume tag size. */ + tsiz = *srcp; + srcp++; + + /* At root, finis. */ + if (tsiz == 0) + break; + + tend = srcp + tsiz; + + /* If the tag exceeds the source buffer, it's illegal. + * This should also trap compression pointers (which should + * not be in these buffers). + */ + if (tend > send) + return -1; + + /* dend-1 leaves room for a trailing dot and quote. */ + status = pretty_escape(dst, dend-1, &srcp, tend); + + if ((status == -1) || ((*dst + 1) > dend)) + return -1; + + **dst = '.'; + (*dst)++; + count += status + 1; + } + while(1); + + return count; +} + +static int pretty_domain(char **dst, char *dend, const unsigned char **src, const unsigned char *send) { diff --git a/common/parse.c b/common/parse.c index ff31e28c..eabf3ed2 100644 --- a/common/parse.c +++ b/common/parse.c @@ -5266,15 +5266,13 @@ int parse_option_token (rv, cfile, fmt, expr, uniform, lookups) break; case 'd': /* Domain name... */ - val = parse_host_name (cfile); - if (!val) { - parse_warn (cfile, "not a valid domain name."); - skip_to_semi (cfile); + t = parse_domain_name(cfile); + if (!t) { + parse_warn(cfile, "not a valid domain name."); + skip_to_semi(cfile); return 0; } - len = strlen (val); - freeval = ISC_TRUE; - goto make_string; + break; case 't': /* Text string... */ token = next_token (&val, &len, cfile); @@ -5286,7 +5284,6 @@ int parse_option_token (rv, cfile, fmt, expr, uniform, lookups) } return 0; } - make_string: if (!make_const_data (&t, (const unsigned char *)val, len, 1, 1, MDL)) log_fatal ("No memory for concatenation"); @@ -5938,3 +5935,42 @@ parse_domain_list(struct parse *cfile, int compress) return t; } +struct expression * +parse_domain_name(struct parse *cfile) +{ + const char *val; + struct expression *t = NULL; + unsigned len; + int result; + unsigned char buf[NS_MAXCDNAME]; + + val = parse_host_name(cfile); + if (!val) { + return NULL; + } + result = MRns_name_pton(val, buf, sizeof(buf)); + /* No longer need val */ + dfree((char *)val, MDL); + + /* result == 1 means the input was fully qualified. + * result == 0 means the input wasn't. + * result == -1 means bad things. + */ + if (result < 0) { + parse_warn(cfile, "Error assembling domain name: %m"); + return NULL; + } + + /* Compute the used length */ + len = 0; + while (buf[len] != 0) { + len += buf[len] + 1; + } + /* Count the last label (0). */ + len++; + + if (!make_const_data(&t, buf, len, 1, 1, MDL)) + log_fatal("No memory for domain name object."); + + return t; +} |