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:
3
CHANGES
3
CHANGES
@@ -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
|
||||
|
@@ -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 $
|
||||
|
316
lib/dns/master.c
316
lib/dns/master.c
@@ -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;
|
||||
|
Reference in New Issue
Block a user