2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-09-01 06:55:30 +00:00

470. [feature] $GENERATE is now supported. See also

doc/misc/migration.
This commit is contained in:
Mark Andrews
2000-09-18 06:50:35 +00:00
parent a7c76f1924
commit 9d3ef72b37
3 changed files with 349 additions and 36 deletions

View File

@@ -1,3 +1,6 @@
470. [feature] $GENERATE is now supported. See also
doc/misc/migration.
469. [bug] "query-source address * port 53;" now works.
468. [bug] dns_master_load*() failed to report file and line

View File

@@ -95,10 +95,8 @@ line.
2.5. Unimplemented BIND 8 Extensions
BIND 8 supports a nonstandard master file directive "$GENERATE" for
automatically generating multiple instances of certain RRs from a
template. This directive is currently unimplemented in BIND 9.
$GENERATE: This deprecated form of getting a literal $ into a domain
name ($$) is no longer supported, use \$ instead.
3. Interoperability Impact of New Protocol Features
@@ -150,4 +148,4 @@ see the man pages in doc/man/bin/rndc.1 and doc/man/bin/rndc.conf.5 for
details. Many of the ndc commands are still unimplemented in rndc.
$Id: migration,v 1.12 2000/09/08 21:34:28 gson Exp $
$Id: migration,v 1.13 2000/09/18 06:50:35 marka Exp $

View File

@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: master.c,v 1.68 2000/09/17 13:08:46 marka Exp $ */
/* $Id: master.c,v 1.69 2000/09/18 06:50:34 marka Exp $ */
#include <config.h>
@@ -77,6 +77,8 @@
*/
#define TOKENSIZ (8*1024)
#define DNS_MASTER_BUFSZ 2048
typedef ISC_LIST(dns_rdatalist_t) rdatalist_head_t;
/*
@@ -440,6 +442,239 @@ loadctx_create(isc_mem_t *mctx, isc_boolean_t age_ttl, dns_name_t *top,
return (result);
}
static isc_result_t
genname(char *name, int it, char *buffer, size_t length) {
char fmt[sizeof("%04000000000d")];
char numbuf[128];
char *cp;
char mode;
int delta = 0;
isc_textregion_t r;
unsigned int n;
unsigned int width;
r.base = buffer;
r.length = length;
while (*name != '\0') {
if (*name == '$') {
name++;
strcpy(fmt, "%d");
/* Get format specifier. */
if (*name == '{' ) {
n = sscanf(name, "{%d,%u,%1[doxX]}",
&delta, &width, &mode);
switch (n) {
case 1:
break;
case 2:
n = snprintf(fmt, sizeof(fmt),
"%%0%ud", width);
break;
case 3:
n = snprintf(fmt, sizeof(fmt),
"%%0%u%c", width, mode);
break;
default:
return (DNS_R_SYNTAX);
}
if (n >= sizeof(fmt))
return (ISC_R_NOSPACE);
/* Skip past closing brace. */
while (*name != '\0' && *name++ != '}')
continue;
}
n = snprintf(numbuf, sizeof(numbuf), fmt, it + delta);
if (n >= sizeof(numbuf))
return (ISC_R_NOSPACE);
cp = numbuf;
while (*cp != '\0') {
if (r.length == 0)
return (ISC_R_NOSPACE);
r.base[0] = *cp++;
isc_textregion_consume(&r, 1);
}
} else if (*name == '\\') {
if (r.length == 0)
return (ISC_R_NOSPACE);
r.base[0] = *name++;
isc_textregion_consume(&r, 1);
if (*name == '\0')
continue;
if (r.length == 0)
return (ISC_R_NOSPACE);
r.base[0] = *name++;
isc_textregion_consume(&r, 1);
} else {
if (r.length == 0)
return (ISC_R_NOSPACE);
r.base[0] = *name++;
isc_textregion_consume(&r, 1);
}
}
if (r.length == 0)
return (ISC_R_NOSPACE);
r.base[0] = '\0';
return (ISC_R_SUCCESS);
}
static isc_result_t
generate(dns_loadctx_t *ctx, char *range, char *lhs, char *gtype, char *rhs) {
char *target_mem = NULL;
char *lhsbuf = NULL;
char *rhsbuf = NULL;
dns_fixedname_t ownerfixed;
dns_name_t *owner;
dns_rdata_t rdata;
dns_rdatacallbacks_t *callbacks;
dns_rdatalist_t rdatalist;
dns_rdatatype_t type;
rdatalist_head_t head;
int n;
int target_size = MINTSIZ; /* only one rdata at a time */
isc_buffer_t buffer;
isc_buffer_t target;
isc_result_t result;
isc_textregion_t r;
unsigned int start, stop, step, i;
callbacks = ctx->callbacks;
dns_fixedname_init(&ownerfixed);
owner = dns_fixedname_name(&ownerfixed);
ISC_LIST_INIT(head);
target_mem = isc_mem_get(ctx->mctx, target_size);
rhsbuf = isc_mem_get(ctx->mctx, DNS_MASTER_BUFSZ);
lhsbuf = isc_mem_get(ctx->mctx, DNS_MASTER_BUFSZ);
if (target_mem == NULL || rhsbuf == NULL || lhsbuf == NULL) {
result = ISC_R_NOMEMORY;
goto error_cleanup;
}
isc_buffer_init(&target, target_mem, target_size);
n = sscanf(range, "%u-%u/%u", &start, &stop, &step);
if (n < 2 || stop < stop) {
(*callbacks->warn)(callbacks,
"%s: %s:%lu: invalid range '%s'",
"$GENERATE",
isc_lex_getsourcename(ctx->lex),
isc_lex_getsourceline(ctx->lex),
range);
result = DNS_R_SYNTAX;
goto insist_cleanup;
}
if (n == 2)
step = 1;
/*
* Get type.
*/
r.base = gtype;
r.length = strlen(gtype);
result = dns_rdatatype_fromtext(&type, &r);
if (result != ISC_R_SUCCESS) {
(*callbacks->warn)(callbacks,
"%s: %s:%lu: unknown RR type '%s'",
"$GENERATE",
isc_lex_getsourcename(ctx->lex),
isc_lex_getsourceline(ctx->lex),
gtype);
goto insist_cleanup;
}
switch (type) {
case dns_rdatatype_ns:
case dns_rdatatype_ptr:
case dns_rdatatype_cname:
break;
case dns_rdatatype_a:
case dns_rdatatype_aaaa:
if (ctx->zclass == dns_rdataclass_in ||
ctx->zclass == dns_rdataclass_hs)
break;
/* FALLTHROUGH */
default:
(*callbacks->warn)(callbacks,
"%s: %s:%lu: unsupported type '%s'",
"$GENERATE",
isc_lex_getsourcename(ctx->lex),
isc_lex_getsourceline(ctx->lex),
gtype);
result = ISC_R_NOTIMPLEMENTED;
goto error_cleanup;
}
for (i = start; i < stop; i += step) {
result = genname(lhs, i, lhsbuf, DNS_MASTER_BUFSZ);
if (result != ISC_R_SUCCESS)
goto error_cleanup;
result = genname(rhs, i, rhsbuf, DNS_MASTER_BUFSZ);
if (result != ISC_R_SUCCESS)
goto error_cleanup;
isc_buffer_init(&buffer, lhsbuf, strlen(lhsbuf));
isc_buffer_add(&buffer, strlen(lhsbuf));
isc_buffer_setactive(&buffer, strlen(lhsbuf));
result = dns_name_fromtext(owner, &buffer, ctx->origin,
ISC_FALSE, NULL);
if (result != ISC_R_SUCCESS)
goto error_cleanup;
isc_buffer_init(&buffer, rhsbuf, strlen(rhsbuf));
isc_buffer_add(&buffer, strlen(rhsbuf));
isc_buffer_setactive(&buffer, strlen(rhsbuf));
result = isc_lex_openbuffer(ctx->lex, &buffer);
if (result != ISC_R_SUCCESS)
goto error_cleanup;
isc_buffer_init(&target, target_mem, target_size);
result = dns_rdata_fromtext(&rdata, ctx->zclass, type,
ctx->lex, ctx->origin, ISC_FALSE,
&target, callbacks);
isc_lex_close(ctx->lex);
if (result != ISC_R_SUCCESS)
goto error_cleanup;
rdatalist.type = type;
rdatalist.covers = 0;
rdatalist.rdclass = ctx->zclass;
rdatalist.ttl = ctx->ttl;
ISC_LIST_INIT(rdatalist.rdata);
ISC_LIST_PREPEND(head, &rdatalist, link);
ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
result = commit(callbacks, ctx->lex, &head, owner,
ctx->top);
if (result != ISC_R_SUCCESS)
goto error_cleanup;
}
result = ISC_R_SUCCESS;
goto cleanup;
error_cleanup:
if (result == ISC_R_NOMEMORY)
(*callbacks->error)(callbacks, "$GENERATE: %s",
dns_result_totext(result));
else
(*callbacks->error)(callbacks, "$GENERATE: %s:%lu: %s",
isc_lex_getsourcename(ctx->lex),
isc_lex_getsourceline(ctx->lex),
dns_result_totext(result));
insist_cleanup:
INSIST(result != ISC_R_SUCCESS);
cleanup:
if (target_mem != NULL)
isc_mem_put(ctx->mctx, target_mem, target_size);
if (lhsbuf != NULL)
isc_mem_put(ctx->mctx, lhsbuf, DNS_MASTER_BUFSZ);
if (rhsbuf != NULL)
isc_mem_put(ctx->mctx, rhsbuf, DNS_MASTER_BUFSZ);
return (result);
}
static isc_result_t
load(dns_loadctx_t **ctxp) {
dns_rdataclass_t rdclass;
@@ -478,6 +713,10 @@ load(dns_loadctx_t **ctxp) {
isc_mem_t *mctx;
dns_rdatacallbacks_t *callbacks;
dns_loadctx_t *ctx;
char *range = NULL;
char *lhs = NULL;
char *gtype = NULL;
char *rhs = NULL;
ctx = *ctxp;
@@ -657,6 +896,72 @@ load(dns_loadctx_t **ctxp) {
ttl_offset = current_time - dump_time;
read_till_eol = ISC_TRUE;
continue;
} else if (strcasecmp(token.value.as_pointer,
"$GENERATE") == 0) {
/*
* Use default ttl if known otherwise
* inherit or error.
*/
if (!ctx->ttl_known &&
!ctx->default_ttl_known) {
(*callbacks->error)(callbacks,
"%s: %s:%lu: no TTL specified",
"dns_master_load",
isc_lex_getsourcename(ctx->lex),
isc_lex_getsourceline(ctx->lex));
result = DNS_R_NOTTL;
goto insist_and_cleanup;
} else if (ctx->default_ttl_known) {
ctx->ttl = ctx->default_ttl;
}
/*
* Lazy cleanup.
*/
if (range != NULL)
isc_mem_free(mctx, range);
if (lhs != NULL)
isc_mem_free(mctx, lhs);
if (gtype != NULL)
isc_mem_free(mctx, gtype);
if (rhs != NULL)
isc_mem_free(mctx, rhs);
/* range */
GETTOKEN(ctx->lex, 0, &token, ISC_FALSE);
range = isc_mem_strdup(mctx,
token.value.as_pointer);
if (range == NULL) {
result = ISC_R_NOMEMORY;
goto log_and_cleanup;
}
/* LHS */
GETTOKEN(ctx->lex, 0, &token, ISC_FALSE);
lhs = isc_mem_strdup(mctx,
token.value.as_pointer);
if (lhs == NULL) {
result = ISC_R_NOMEMORY;
goto log_and_cleanup;
}
/* TYPE */
GETTOKEN(ctx->lex, 0, &token, ISC_FALSE);
gtype = isc_mem_strdup(mctx,
token.value.as_pointer);
if (gtype == NULL) {
result = ISC_R_NOMEMORY;
goto log_and_cleanup;
}
/* RHS */
GETTOKEN(ctx->lex, 0, &token, ISC_FALSE);
rhs = isc_mem_strdup(mctx,
token.value.as_pointer);
if (rhs == NULL) {
result = ISC_R_NOMEMORY;
goto log_and_cleanup;
}
result = generate(ctx, range, lhs, gtype, rhs);
if (result != ISC_R_SUCCESS)
goto insist_and_cleanup;
read_till_eol = ISC_TRUE;
continue;
} else if (strncasecmp(token.value.as_pointer,
"$", 1) == 0) {
(callbacks->error)(callbacks,
@@ -1111,6 +1416,14 @@ load(dns_loadctx_t **ctxp) {
isc_mem_put(mctx, target_mem, target_size);
if (include_file != NULL)
isc_mem_free(mctx, include_file);
if (range != NULL)
isc_mem_free(mctx, range);
if (lhs != NULL)
isc_mem_free(mctx, lhs);
if (gtype != NULL)
isc_mem_free(mctx, gtype);
if (rhs != NULL)
isc_mem_free(mctx, rhs);
return (result);
}
@@ -1155,7 +1468,6 @@ pushfile(const char *master_file, dns_name_t *origin, dns_loadctx_t **ctxp) {
CTX_COPYVAR(ctx, new, default_ttl);
CTX_COPYVAR(ctx, new, warn_1035);
result = isc_lex_openfile(new->lex, master_file);
if (result != ISC_R_SUCCESS)
goto cleanup;