diff --git a/afsdb.c b/afsdb.c index 69ca2e2..877d149 100644 --- a/afsdb.c +++ b/afsdb.c @@ -21,7 +21,7 @@ static struct rr *afsdb_parse(char *name, long ttl, int type, char *s) { struct rr_afsdb *rr = getmem(sizeof(*rr)); - rr->subtype = extract_integer(&s, "AFSDB subtype"); + rr->subtype = extract_integer(&s, "AFSDB subtype", NULL); if (rr->subtype < 0) return NULL; diff --git a/cert.c b/cert.c index d17576e..d4b551d 100644 --- a/cert.c +++ b/cert.c @@ -30,7 +30,7 @@ static int extract_certificate_type(char **s, char *what) char *str_type; if (isdigit(**s)) { - type = extract_integer(s, what); + type = extract_integer(s, what, NULL); if (type >= 1 && type <= 8) return type; if (type == 253 || type == 254) @@ -84,14 +84,14 @@ static struct rr* cert_parse(char *name, long ttl, int type, char *s) if (cert_type < 0) return NULL; rr->type = cert_type; - key_tag = extract_integer(&s, "key tag"); + key_tag = extract_integer(&s, "key tag", NULL); if (key_tag < 0) return NULL; if (key_tag > 65535) return bitch("bad key tag"); rr->key_tag = key_tag; if (isdigit(*s)) { - alg = extract_integer(&s, "algorithm"); + alg = extract_integer(&s, "algorithm", NULL); if (alg < 0) return NULL; if (alg > 255) return bitch("bad algorithm"); if (alg != 0) { /* 0 is just fine */ diff --git a/common.h b/common.h index 23e8a5d..2ef062f 100644 --- a/common.h +++ b/common.h @@ -18,6 +18,11 @@ struct file_info char buf[2048]; char *current_origin; char name[0]; + + int generate_cur; + int generate_lim; + int generate_lhs; + int generate_rhs; }; extern struct file_info *file_info; diff --git a/dlv.c b/dlv.c index eba109d..8e7d078 100644 --- a/dlv.c +++ b/dlv.c @@ -22,7 +22,7 @@ static struct rr* dlv_parse(char *name, long ttl, int type, char *s) struct rr_dlv *rr = getmem(sizeof(*rr)); int key_tag, algorithm, digest_type; - key_tag = extract_integer(&s, "key tag"); + key_tag = extract_integer(&s, "key tag", NULL); if (key_tag < 0) return NULL; rr->key_tag = key_tag; @@ -30,7 +30,7 @@ static struct rr* dlv_parse(char *name, long ttl, int type, char *s) if (algorithm == ALG_UNSUPPORTED) return NULL; rr->algorithm = algorithm; - digest_type = extract_integer(&s, "digest type"); + digest_type = extract_integer(&s, "digest type", NULL); if (digest_type < 0) return NULL; rr->digest_type = digest_type; diff --git a/dnskey.c b/dnskey.c index 0822e71..fecc62a 100644 --- a/dnskey.c +++ b/dnskey.c @@ -31,7 +31,7 @@ static struct rr* dnskey_parse(char *name, long ttl, int type, char *s) int i; static struct rr *result; - flags = extract_integer(&s, "flags"); + flags = extract_integer(&s, "flags", NULL); if (flags < 0) return NULL; if (flags & 0xfe7e) return bitch("reserved flags bits are set"); @@ -41,7 +41,7 @@ static struct rr* dnskey_parse(char *name, long ttl, int type, char *s) /* TODO validate that `name` is the name of the zone if flags have Zone Key bit set */ - proto = extract_integer(&s, "protocol"); + proto = extract_integer(&s, "protocol", NULL); if (proto < 0) return NULL; if (proto != 3) return bitch("bad protocol value"); diff --git a/ds.c b/ds.c index d451af4..947f929 100644 --- a/ds.c +++ b/ds.c @@ -22,7 +22,7 @@ static struct rr* ds_parse(char *name, long ttl, int type, char *s) struct rr_ds *rr = getmem(sizeof(*rr)); int key_tag, algorithm, digest_type; - key_tag = extract_integer(&s, "key tag"); + key_tag = extract_integer(&s, "key tag", NULL); if (key_tag < 0) return NULL; rr->key_tag = key_tag; @@ -30,7 +30,7 @@ static struct rr* ds_parse(char *name, long ttl, int type, char *s) if (algorithm == ALG_UNSUPPORTED) return NULL; rr->algorithm = algorithm; - digest_type = extract_integer(&s, "digest type"); + digest_type = extract_integer(&s, "digest type", NULL); if (digest_type < 0) return NULL; rr->digest_type = digest_type; diff --git a/ipseckey.c b/ipseckey.c index 2c07748..c5bdf94 100644 --- a/ipseckey.c +++ b/ipseckey.c @@ -24,15 +24,15 @@ static struct rr *ipseckey_parse(char *name, long ttl, int type, char *s) struct rr_ipseckey *rr = getmem(sizeof(*rr)); int i; - rr->precedence = i = extract_integer(&s, "precedence"); + rr->precedence = i = extract_integer(&s, "precedence", NULL); if (i < 0) return NULL; if (i >= 256) return bitch("precedence range is not valid"); - rr->gateway_type = i = extract_integer(&s, "gateway type"); + rr->gateway_type = i = extract_integer(&s, "gateway type", NULL); if (i < 0) return NULL; if (i > 3) return bitch("gateway type is not valid"); - rr->algorithm = i = extract_integer(&s, "algorithm"); + rr->algorithm = i = extract_integer(&s, "algorithm", NULL); if (i < 0) return NULL; if (i > 2) return bitch("algorithm is not valid"); diff --git a/kx.c b/kx.c index fc81d23..f69ba1b 100644 --- a/kx.c +++ b/kx.c @@ -21,7 +21,7 @@ static struct rr *kx_parse(char *name, long ttl, int type, char *s) { struct rr_kx *rr = getmem(sizeof(*rr)); - rr->preference = extract_integer(&s, "KX preference"); + rr->preference = extract_integer(&s, "KX preference", NULL); if (rr->preference < 0) return NULL; diff --git a/l32.c b/l32.c index cba2098..a4cdbd6 100644 --- a/l32.c +++ b/l32.c @@ -23,7 +23,7 @@ static struct rr *l32_parse(char *name, long ttl, int type, char *s) struct in_addr ipv4_like; int preference; - rr->preference = preference = extract_integer(&s, "L32 preference"); + rr->preference = preference = extract_integer(&s, "L32 preference", NULL); if (preference < 0) return NULL; if (extract_ipv4(&s, "Locator32", &ipv4_like) <= 0) diff --git a/l64.c b/l64.c index 370a080..896db54 100644 --- a/l64.c +++ b/l64.c @@ -22,7 +22,7 @@ static struct rr *l64_parse(char *name, long ttl, int type, char *s) struct rr_l64 *rr = getmem(sizeof(*rr)); int preference; - rr->preference = preference = extract_integer(&s, "L64 preference"); + rr->preference = preference = extract_integer(&s, "L64 preference", NULL); if (preference < 0) return NULL; if (extract_u64(&s, "Locator64", &rr->locator64) < 0) diff --git a/loc.c b/loc.c index a5fb432..81264e5 100644 --- a/loc.c +++ b/loc.c @@ -56,7 +56,7 @@ static struct rr *loc_parse(char *name, long ttl, int type, char *s) rr->version = 0; /* latitude block */ - i = extract_integer(&s, "degrees latitude"); + i = extract_integer(&s, "degrees latitude", NULL); if (i < 0) return NULL; if (i > 90) @@ -65,7 +65,7 @@ static struct rr *loc_parse(char *name, long ttl, int type, char *s) min = 0; sec = 0; if (isdigit(*s)) { - i = extract_integer(&s, "minutes latitude"); + i = extract_integer(&s, "minutes latitude", NULL); if (i < 0) return NULL; if (i > 59) @@ -96,7 +96,7 @@ static struct rr *loc_parse(char *name, long ttl, int type, char *s) if (!s) return NULL; /* longitude block */ - i = extract_integer(&s, "degrees longitude"); + i = extract_integer(&s, "degrees longitude", NULL); if (i < 0) return NULL; if (i > 180) @@ -105,7 +105,7 @@ static struct rr *loc_parse(char *name, long ttl, int type, char *s) min = 0; sec = 0; if (isdigit(*s)) { - i = extract_integer(&s, "minutes longitude"); + i = extract_integer(&s, "minutes longitude", NULL); if (i < 0) return NULL; if (i > 59) diff --git a/lp.c b/lp.c index 871a4de..ddf5aa3 100644 --- a/lp.c +++ b/lp.c @@ -23,7 +23,7 @@ static struct rr *lp_parse(char *name, long ttl, int type, char *s) struct rr_lp *rr = getmem(sizeof(*rr)); int preference; - rr->preference = preference = extract_integer(&s, "LP preference"); + rr->preference = preference = extract_integer(&s, "LP preference", NULL); if (preference < 0) return NULL; rr->fqdn = extract_name(&s, "LP fqdn", 0); diff --git a/main.c b/main.c index d67104a..433a1c6 100644 --- a/main.c +++ b/main.c @@ -72,6 +72,39 @@ static char *process_directive(char *s) fprintf(stderr, "-> %s:%d: ", file_info->name, file_info->line); fprintf(stderr, "default ttl is now %ld\n", G.default_ttl); } + } else if (*(s+1) == 'G' && strncmp(s, "$GENERATE", 9) == 0) { + int from, to; + char *lhs, *rhs; + + s += 9; + if (!isspace(*s)) { + if (isalnum(*s)) goto unrecognized_directive; + return bitch("bad $GENERATE format"); + } + s = skip_white_space(s); + + from = extract_integer(&s, "generate-from", "-"); + if (from < 0) + return NULL; + if (*s != '-') + return bitch("'-' between generate-from and generate-to is expected"); + s++; + to = extract_integer(&s, "generate-to", "-"); + if (to < 0) + return NULL; + + if (*s == '/') + return bitch("generate-step is unsupported for now"); + + lhs = extract_name(&s, "generate-lhs", KEEP_CAPITALIZATION | DOLLAR_OK_IN_NAMES); + if (!lhs) + return NULL; + + if (*s == '{') + return bitch("{offset,width,type} is unsupported for now"); + + rhs = quickstrdup(s); + return rhs; } else if (*(s+1) == 'I' && strncmp(s, "$INCLUDE", 8) == 0) { char *p, *f; char c; diff --git a/mx.c b/mx.c index bf295fd..8c873f3 100644 --- a/mx.c +++ b/mx.c @@ -21,7 +21,7 @@ static struct rr *mx_parse(char *name, long ttl, int type, char *s) { struct rr_mx *rr = getmem(sizeof(*rr)); - rr->preference = extract_integer(&s, "MX preference"); + rr->preference = extract_integer(&s, "MX preference", NULL); if (rr->preference < 0) return NULL; /* XXX preference range check */ diff --git a/naptr.c b/naptr.c index 99a2c83..da9472a 100644 --- a/naptr.c +++ b/naptr.c @@ -24,14 +24,14 @@ static struct rr *naptr_parse(char *name, long ttl, int type, char *s) int i; struct binary_data text; - i = extract_integer(&s, "order"); + i = extract_integer(&s, "order", NULL); if (i < 0) return NULL; if (i >= 65536) return bitch("order range is not valid"); rr->order = i; - i = extract_integer(&s, "preference"); + i = extract_integer(&s, "preference", NULL); if (i < 0) return NULL; if (i >= 65536) diff --git a/nid.c b/nid.c index 12d6f57..3d0e030 100644 --- a/nid.c +++ b/nid.c @@ -22,7 +22,7 @@ static struct rr *nid_parse(char *name, long ttl, int type, char *s) struct rr_nid *rr = getmem(sizeof(*rr)); int preference; - rr->preference = preference = extract_integer(&s, "NID preference"); + rr->preference = preference = extract_integer(&s, "NID preference", NULL); if (preference < 0) return NULL; if (extract_u64(&s, "NodeID", &rr->node_id) < 0) diff --git a/nsec3.c b/nsec3.c index e59e396..c2440fa 100644 --- a/nsec3.c +++ b/nsec3.c @@ -31,7 +31,7 @@ static struct rr* nsec3_parse(char *name, long ttl, int type, char *s) char *str_type = NULL; int ltype; - i = extract_integer(&s, "hash algorithm"); + i = extract_integer(&s, "hash algorithm", NULL); if (i < 0) return NULL; if (i > 255) @@ -40,7 +40,7 @@ static struct rr* nsec3_parse(char *name, long ttl, int type, char *s) return bitch("unrecognized or unsupported hash algorithm"); rr->hash_algorithm = i; - i = extract_integer(&s, "flags"); + i = extract_integer(&s, "flags", NULL); if (i < 0) return NULL; if (i > 255) @@ -52,7 +52,7 @@ static struct rr* nsec3_parse(char *name, long ttl, int type, char *s) opt_out = 1; rr->flags = i; - i = extract_integer(&s, "iterations"); + i = extract_integer(&s, "iterations", NULL); if (i < 0) return NULL; if (i > 2500) diff --git a/nsec3param.c b/nsec3param.c index af3fe98..72eb48f 100644 --- a/nsec3param.c +++ b/nsec3param.c @@ -27,7 +27,7 @@ static struct rr* nsec3param_parse(char *name, long ttl, int type, char *s) struct rr *ret_rr; int i; - i = extract_integer(&s, "hash algorithm"); + i = extract_integer(&s, "hash algorithm", NULL); if (i < 0) return NULL; if (i > 255) @@ -36,7 +36,7 @@ static struct rr* nsec3param_parse(char *name, long ttl, int type, char *s) return bitch("unrecognized or unsupported hash algorithm"); rr->hash_algorithm = i; - i = extract_integer(&s, "flags"); + i = extract_integer(&s, "flags", NULL); if (i < 0) return NULL; if (i > 255) @@ -45,7 +45,7 @@ static struct rr* nsec3param_parse(char *name, long ttl, int type, char *s) return bitch("flags is supposed to be 0 for NSEC3PARAM"); rr->flags = i; - i = extract_integer(&s, "iterations"); + i = extract_integer(&s, "iterations", NULL); if (i < 0) return NULL; if (i > 2500) diff --git a/px.c b/px.c index 81a4f47..0c8aaca 100644 --- a/px.c +++ b/px.c @@ -21,7 +21,7 @@ static struct rr *px_parse(char *name, long ttl, int type, char *s) { struct rr_px *rr = getmem(sizeof(*rr)); - rr->preference = extract_integer(&s, "PX preference"); + rr->preference = extract_integer(&s, "PX preference", NULL); if (rr->preference < 0) return NULL; diff --git a/rr.c b/rr.c index 34bccdf..022bb89 100644 --- a/rr.c +++ b/rr.c @@ -432,7 +432,7 @@ struct rr *rr_parse_any(char *name, long ttl, int type, char *s) s = skip_white_space(s); if (!s) return NULL; - len = extract_integer(&s, "custom data size"); + len = extract_integer(&s, "custom data size", NULL); if (len < 0) return NULL; if (len > 65535) goto invalid; @@ -810,7 +810,7 @@ int extract_algorithm(char **s, char *what) char *str_alg; if (isdigit(**s)) { - alg = extract_integer(s, what); + alg = extract_integer(s, what, NULL); if (algorithm_type(alg) == ALG_UNSUPPORTED) { bitch("bad or unsupported algorithm %d", alg); return ALG_UNSUPPORTED; diff --git a/rrsig.c b/rrsig.c index ed4333a..81f24b4 100644 --- a/rrsig.c +++ b/rrsig.c @@ -64,7 +64,7 @@ static struct rr* rrsig_parse(char *name, long ttl, int type, char *s) return bitch("private algorithms are not supported in RRSIG"); } - rr->labels = extract_integer(&s, "labels"); + rr->labels = extract_integer(&s, "labels", NULL); if (rr->labels < 0) return NULL; /* TODO validate labels, see http://tools.ietf.org/html/rfc4034#section-3.1.3 */ @@ -79,7 +79,7 @@ static struct rr* rrsig_parse(char *name, long ttl, int type, char *s) if (ts < 0) return NULL; rr->sig_inception = ts; - key_tag = extract_integer(&s, "key tag"); + key_tag = extract_integer(&s, "key tag", NULL); if (key_tag < 0) return NULL; rr->key_tag = key_tag; diff --git a/rt.c b/rt.c index 5c1776f..3bb53bf 100644 --- a/rt.c +++ b/rt.c @@ -21,7 +21,7 @@ static struct rr *rt_parse(char *name, long ttl, int type, char *s) { struct rr_rt *rr = getmem(sizeof(*rr)); - rr->preference = extract_integer(&s, "RT preference"); + rr->preference = extract_integer(&s, "RT preference", NULL); if (rr->preference < 0) return NULL; diff --git a/soa.c b/soa.c index e8b5fe5..028464e 100644 --- a/soa.c +++ b/soa.c @@ -27,7 +27,7 @@ static struct rr* soa_parse(char *name, long ttl, int type, char *s) if (!rr->mname) return NULL; rr->rname = extract_name(&s, "rname", 0); if (!rr->rname) return NULL; - i = extract_integer(&s, "serial"); + i = extract_integer(&s, "serial", NULL); if (i < 0) return NULL; if (i > 4294967295UL) return bitch("serial is out of range"); rr->serial = i; diff --git a/srv.c b/srv.c index e3ddc0d..808dade 100644 --- a/srv.c +++ b/srv.c @@ -24,21 +24,21 @@ static struct rr *srv_parse(char *name, long ttl, int type, char *s) /* TODO validate `name` (underscores etc) http://tools.ietf.org/html/rfc2782 */ - i = extract_integer(&s, "priority"); + i = extract_integer(&s, "priority", NULL); if (i < 0) return NULL; if (i >= 65536) return bitch("priority range is not valid"); rr->priority = i; - i = extract_integer(&s, "weight"); + i = extract_integer(&s, "weight", NULL); if (i < 0) return NULL; if (i >= 65536) return bitch("weight range is not valid"); rr->weight = i; - i = extract_integer(&s, "port"); + i = extract_integer(&s, "port", NULL); if (i < 0) return NULL; if (i >= 65536) diff --git a/sshfp.c b/sshfp.c index 66a2d92..55b78f3 100644 --- a/sshfp.c +++ b/sshfp.c @@ -22,13 +22,13 @@ static struct rr* sshfp_parse(char *name, long ttl, int type, char *s) struct rr_sshfp *rr = getmem(sizeof(*rr)); int algorithm, fp_type; - algorithm = extract_integer(&s, "algorithm"); + algorithm = extract_integer(&s, "algorithm", NULL); if (algorithm < 0) return NULL; if (algorithm != 1 && algorithm != 2 && algorithm != 3 && algorithm != 4) return bitch("unsupported algorithm"); rr->algorithm = algorithm; - fp_type = extract_integer(&s, "fp type"); + fp_type = extract_integer(&s, "fp type", NULL); if (fp_type < 0) return NULL; if (fp_type != 1 && fp_type != 2) return bitch("unsupported fp_type"); diff --git a/textparse.c b/textparse.c index d190e77..50e06d3 100644 --- a/textparse.c +++ b/textparse.c @@ -77,7 +77,7 @@ static char *extract_name_slow(char **input, char *what, int options) int d, l, ol; while (1) { - if (isalnum(*s) || *s == '_' || *s == '.' || *s == '-' || *s == '/') { + if (isalnum(*s) || *s == '_' || *s == '.' || *s == '-' || *s == '/' || ((options & DOLLAR_OK_IN_NAMES) && *s == '$')) { if (t-buf >= 1022) return bitch("name too long"); *t++ = *s++; @@ -182,7 +182,7 @@ char *extract_name(char **input, char *what, int options) } r = quickstrdup(file_info->current_origin); } else { - if (!(isalnum(*s) || *s == '_' || *s == '.' || *s == '/')) { + if (!(isalnum(*s) || *s == '_' || *s == '.' || *s == '/' || ((options & DOLLAR_OK_IN_NAMES) && *s == '$'))) { if (*s == '*') { wildcard = 1; } else { @@ -192,7 +192,7 @@ char *extract_name(char **input, char *what, int options) } } s++; - while (isalnum(*s) || *s == '.' || *s == '-' || *s == '_' || *s == '/') + while (isalnum(*s) || *s == '.' || *s == '-' || *s == '_' || *s == '/' || ((options & DOLLAR_OK_IN_NAMES) && *s == '$')) s++; if (*s && !isspace(*s) && *s != ';' && *s != ')') { if (*s == '\\') @@ -277,7 +277,7 @@ char *extract_label(char **input, char *what, void *is_temporary) return r; } -long long extract_integer(char **input, char *what) +long long extract_integer(char **input, char *what, const char *extra_delimiters) { char *s = *input; long long r = -1; @@ -292,8 +292,10 @@ long long extract_integer(char **input, char *what) while (isdigit(*s)) s++; if (*s && !isspace(*s) && *s != ';' && *s != ')') { - bitch("%s is not valid", what); - return -1; + if (!extra_delimiters || strchr(extra_delimiters, *s) == NULL) { + bitch("%s is not valid", what); + return -1; + } } if (!*s) end = s; c = *s; diff --git a/textparse.h b/textparse.h index 9fd0501..8287020 100644 --- a/textparse.h +++ b/textparse.h @@ -33,12 +33,13 @@ struct binary_data compose_binary_data(const char *fmt, int tmp, ...); */ #define KEEP_CAPITALIZATION 32 +#define DOLLAR_OK_IN_NAMES 64 int empty_line_or_comment(char *s); char *skip_white_space(char *s); char *extract_name(char **input, char *what, int options); char *extract_label(char **input, char *what, void *is_temporary); -long long extract_integer(char **input, char *what); +long long extract_integer(char **input, char *what, const char *extra_delimiters); long extract_timevalue(char **input, char *what); long long extract_timestamp(char **input, char *what); int extract_ipv4(char **input, char *what, struct in_addr *addr); diff --git a/tlsa.c b/tlsa.c index 6783ece..5cbd3c7 100644 --- a/tlsa.c +++ b/tlsa.c @@ -28,19 +28,19 @@ static struct rr* tlsa_parse(char *name, long ttl, int type, char *s) struct rr_tlsa *rr = getmem(sizeof(*rr)); int cert_usage, selector, matching_type; - cert_usage = extract_integer(&s, "certificate usage field"); + cert_usage = extract_integer(&s, "certificate usage field", NULL); if (cert_usage < 0) return NULL; if (cert_usage > 3) return bitch("bad certificate usage field"); rr->cert_usage = cert_usage; - selector = extract_integer(&s, "selector field"); + selector = extract_integer(&s, "selector field", NULL); if (selector < 0) return NULL; if (selector > 1) return bitch("bad selector field"); rr->selector = selector; - matching_type = extract_integer(&s, "matching type field"); + matching_type = extract_integer(&s, "matching type field", NULL); if (matching_type < 0) return NULL; if (matching_type > 2) return bitch("bad matching type field");