Commit 6c21e4ae authored by Jan Včelák's avatar Jan Včelák 🚀

Merge branch 'zscanner-api-extension' into 'master'

parents 0b60906a 4d08662f
......@@ -13,8 +13,7 @@ ragel -T0 -s -o $OUT_T0 $IN
# Remove redundant comments and unused constants (clang warnings).
sed -i '/#line/d' $OUT_T0
sed -i '/static\ const\ int\ zone_scanner_en_/d' $OUT_T0
sed -i '/zone_scanner_first_final/d' $OUT_T0
sed -i '/static\ const\ int\ zone_scanner_/d' $OUT_T0
# Remove trailing white spaces.
sed -i 's/\s*$//g' $OUT_T0
......@@ -24,8 +23,7 @@ ragel -G2 -s -o $OUT_G2 $IN
# Remove redundant comments and unused constants (clang warnings).
sed -i '/#line/d' $OUT_G2
sed -i '/static\ const\ int\ zone_scanner_en_/d' $OUT_G2
sed -i '/zone_scanner_first_final/d' $OUT_G2
sed -i '/static\ const\ int\ zone_scanner_/d' $OUT_G2
# Remove trailing white spaces.
sed -i 's/\s*$//g' $OUT_G2
......
......@@ -33,22 +33,23 @@
*
* \todo Currently, the function waits for the first DNSKEY record, and skips
* the others. We should be more strict and report other records as errors.
* However, there is currently no API to stop the scanner.
*/
static void parse_record(zs_scanner_t *scanner)
{
assert(scanner);
assert(scanner->data);
assert(scanner->process.data);
dnssec_key_t *key = scanner->data;
dnssec_key_t *key = scanner->process.data;
if (dnssec_key_get_dname(key) != NULL) {
// skip till the the parser finishes
// should report error
scanner->state = ZS_STATE_STOP;
return;
}
if (scanner->r_type != RTYPE_DNSKEY) {
// should report error
scanner->state = ZS_STATE_STOP;
return;
}
......@@ -73,16 +74,25 @@ int legacy_pubkey_parse(const char *filename, dnssec_key_t **key_ptr)
uint16_t cls = CLASS_IN;
uint32_t ttl = 0;
zs_scanner_t *scanner = zs_scanner_create(".", cls, ttl,
parse_record, NULL, key);
if (!scanner) {
zs_scanner_t *scanner = malloc(sizeof(zs_scanner_t));
if (scanner == NULL) {
dnssec_key_free(key);
return DNSSEC_ENOMEM;
}
if (zs_init(scanner, ".", cls, ttl) != 0 ||
zs_set_input_file(scanner, filename) != 0 ||
zs_set_processing(scanner, parse_record, NULL, key) != 0 ||
zs_parse_all(scanner) != 0) {
zs_deinit(scanner);
free(scanner);
dnssec_key_free(key);
return DNSSEC_NOT_FOUND;
}
zs_deinit(scanner);
free(scanner);
result = zs_scanner_parse_file(scanner, filename);
zs_scanner_free(scanner);
if (result != 0 || dnssec_key_get_dname(key) == NULL) {
if (dnssec_key_get_dname(key) == NULL) {
dnssec_key_free(key);
return DNSSEC_INVALID_PUBLIC_KEY;
}
......
......@@ -171,7 +171,7 @@ size_t estimator_trie_htable_memsize(hattrie_t *table)
void estimator_rrset_memsize_wrap(zs_scanner_t *scanner)
{
rrset_memsize(scanner->data, scanner);
rrset_memsize(scanner->process.data, scanner);
}
int estimator_free_trie_node(value_t *val, void *data)
......
......@@ -796,6 +796,12 @@ static int cmd_checkzone(cmd_args_t *args)
static int cmd_memstats(cmd_args_t *args)
{
zs_scanner_t *zs = malloc(sizeof(zs_scanner_t));
if (zs == NULL) {
log_error("not enough memory");
return 1;
}
/* Zone checking */
double total_size = 0;
......@@ -835,28 +841,29 @@ static int cmd_memstats(cmd_args_t *args)
conf_iter_finish(conf(), &iter);
break;
}
zs_scanner_t *zs = zs_scanner_create(zone_name,
KNOT_CLASS_IN, 3600,
estimator_rrset_memsize_wrap,
NULL, &est);
free(zone_name);
if (zs == NULL) {
if (zs_init(zs, zone_name, KNOT_CLASS_IN, 3600) != 0 ||
zs_set_processing(zs, estimator_rrset_memsize_wrap, NULL, &est) != 0) {
log_zone_error(conf_dname(&id), "failed to load zone");
zs_deinit(zs);
free(zone_name);
hattrie_free(est.node_table);
continue;
}
free(zone_name);
/* Do a parser run, but do not actually create the zone. */
char *zonefile = conf_zonefile(conf(), conf_dname(&id));
int ret = zs_scanner_parse_file(zs, zonefile);
free(zonefile);
if (ret != 0) {
if (zs_set_input_file(zs, zonefile) != 0 ||
zs_parse_all(zs) != 0) {
log_zone_error(conf_dname(&id), "failed to parse zone");
hattrie_apply_rev(est.node_table, estimator_free_trie_node, NULL);
hattrie_free(est.node_table);
zs_scanner_free(zs);
free(zonefile);
zs_deinit(zs);
continue;
}
free(zonefile);
zs_deinit(zs);
/* Only size of ahtables inside trie's nodes is missing. */
assert(est.htable_size == 0);
......@@ -874,10 +881,11 @@ static int cmd_memstats(cmd_args_t *args)
log_zone_info(conf_dname(&id), "%zu RRs, used memory estimation is %zu MB",
est.record_count, (size_t)zone_size);
zs_scanner_free(zs);
total_size += zone_size;
}
free(zs);
if (args->argc == 0) { // for all zones
log_info("estimated memory consumption for all zones is %zu MB",
(size_t)total_size);
......
......@@ -59,7 +59,7 @@ static void help(FILE *stream)
/* Global instance of RR scanner. */
static void parse_err(zs_scanner_t *s) {
fprintf(stderr, "failed to parse RDATA: %s\n", zs_strerror(s->error_code));
fprintf(stderr, "failed to parse RDATA: %s\n", zs_strerror(s->error.code));
}
static zs_scanner_t *g_scanner = NULL;
......@@ -99,16 +99,24 @@ int main(int argc, char *argv[])
argv += 3;
argc -= 3;
g_scanner = zs_scanner_create(".", KNOT_CLASS_IN, 0, NULL, parse_err, NULL);
g_scanner = malloc(sizeof(zs_scanner_t));
if (g_scanner == NULL) {
return EXIT_FAILURE;
}
if (zs_init(g_scanner, ".", KNOT_CLASS_IN, 0) != 0 ||
zs_set_processing(g_scanner, NULL, parse_err, NULL) != 0) {
zs_deinit(g_scanner);
free(g_scanner);
return EXIT_FAILURE;
}
/* Open cache for operations. */
struct cache *cache = cache_open(dbdir, 0, NULL);
if (cache == NULL) {
fprintf(stderr, "failed to open db '%s'\n", dbdir);
zs_scanner_free(g_scanner);
zs_deinit(g_scanner);
free(g_scanner);
return EXIT_FAILURE;
}
......@@ -147,7 +155,8 @@ int main(int argc, char *argv[])
}
cache_close(cache);
zs_scanner_free(g_scanner);
zs_deinit(g_scanner);
free(g_scanner);
if (!found) {
help(stderr);
......@@ -168,17 +177,17 @@ static int parse_rdata(struct entry *entry, const char *owner, const char *rrtyp
/* Synthetize RR line */
char *rr_line = sprintf_alloc("%s %u IN %s %s\n", owner, ttl, rrtype, rdata);
ret = zs_scanner_parse(g_scanner, rr_line, rr_line + strlen(rr_line), true);
if (zs_set_input_string(g_scanner, rr_line, strlen(rr_line)) != 0 ||
zs_parse_all(g_scanner) != 0) {
free(rr_line);
return KNOT_EPARSEFAIL;
}
free(rr_line);
/* Write parsed RDATA. */
if (ret == KNOT_EOK) {
knot_rdata_t rr[knot_rdata_array_size(g_scanner->r_data_length)];
knot_rdata_init(rr, g_scanner->r_data_length, g_scanner->r_data, ttl);
ret = knot_rdataset_add(&entry->data.rrs, rr, mm);
}
return ret;
knot_rdata_t rr[knot_rdata_array_size(g_scanner->r_data_length)];
knot_rdata_init(rr, g_scanner->r_data_length, g_scanner->r_data, ttl);
return knot_rdataset_add(&entry->data.rrs, rr, mm);
}
static int rosedb_add(struct cache *cache, MDB_txn *txn, int argc, char *argv[])
......
......@@ -41,19 +41,19 @@
static void process_error(zs_scanner_t *s)
{
zcreator_t *zc = s->data;
zcreator_t *zc = s->process.data;
const knot_dname_t *zname = zc->z->apex->owner;
ERROR(zname, "%s in zone, file '%s', line %"PRIu64" (%s)",
s->stop ? "fatal error" : "error",
s->error.fatal ? "fatal error" : "error",
s->file.name, s->line_counter,
zs_strerror(s->error_code));
zs_strerror(s->error.code));
}
static int add_rdata_to_rr(knot_rrset_t *rrset, const zs_scanner_t *scanner)
{
return knot_rrset_add_rdata(rrset, scanner->r_data, scanner->r_data_length,
scanner->r_ttl, NULL);
scanner->r_ttl, NULL);
}
static void log_ttl_error(const zone_contents_t *zone, const zone_node_t *node,
......@@ -142,11 +142,11 @@ int zcreator_step(zcreator_t *zc, const knot_rrset_t *rr)
}
/*! \brief Creates RR from parser input, passes it to handling function. */
static void scanner_process(zs_scanner_t *scanner)
static void process_data(zs_scanner_t *scanner)
{
zcreator_t *zc = scanner->data;
zcreator_t *zc = scanner->process.data;
if (zc->ret != KNOT_EOK) {
scanner->stop = true;
scanner->state = ZS_STATE_STOP;
return;
}
......@@ -190,6 +190,8 @@ int zonefile_open(zloader_t *loader, const char *source,
return KNOT_EINVAL;
}
memset(loader, 0, sizeof(zloader_t));
/* Check zone file. */
if (access(source, F_OK | R_OK) != 0) {
return KNOT_EACCES;
......@@ -215,19 +217,17 @@ int zonefile_open(zloader_t *loader, const char *source,
return KNOT_ENOMEM;
}
/* Create file loader. */
memset(loader, 0, sizeof(zloader_t));
loader->scanner = zs_scanner_create(origin_str, KNOT_CLASS_IN, 3600,
scanner_process, process_error,
zc);
if (loader->scanner == NULL) {
if (zs_init(&loader->scanner, origin_str, KNOT_CLASS_IN, 3600) != 0 ||
zs_set_input_file(&loader->scanner, source) != 0 ||
zs_set_processing(&loader->scanner, process_data, process_error, zc) != 0) {
zs_deinit(&loader->scanner);
free(origin_str);
free(zc);
return KNOT_ERROR;
}
free(origin_str);
loader->source = strdup(source);
loader->origin = origin_str;
loader->creator = zc;
loader->semantic_checks = semantic_checks;
......@@ -244,10 +244,10 @@ zone_contents_t *zonefile_load(zloader_t *loader)
const knot_dname_t *zname = zc->z->apex->owner;
assert(zc);
int ret = zs_scanner_parse_file(loader->scanner, loader->source);
if (ret != 0 && loader->scanner->error_counter == 0) {
int ret = zs_parse_all(&loader->scanner);
if (ret != 0 && loader->scanner.error.counter == 0) {
ERROR(zname, "failed to load zone, file '%s' (%s)",
loader->source, zs_strerror(loader->scanner->error_code));
loader->source, zs_strerror(loader->scanner.error.code));
goto fail;
}
......@@ -257,9 +257,9 @@ zone_contents_t *zonefile_load(zloader_t *loader)
goto fail;
}
if (loader->scanner->error_counter > 0) {
if (loader->scanner.error.counter > 0) {
ERROR(zname, "failed to load zone, file '%s', %"PRIu64" errors",
loader->source, loader->scanner->error_counter);
loader->source, loader->scanner.error.counter);
goto fail;
}
......@@ -271,11 +271,10 @@ zone_contents_t *zonefile_load(zloader_t *loader)
zone_node_t *first_nsec3_node = NULL;
zone_node_t *last_nsec3_node = NULL;
int kret = zone_contents_adjust_full(zc->z,
&first_nsec3_node, &last_nsec3_node);
if (kret != KNOT_EOK) {
ret = zone_contents_adjust_full(zc->z, &first_nsec3_node, &last_nsec3_node);
if (ret != KNOT_EOK) {
ERROR(zname, "failed to finalize zone contents (%s)",
knot_strerror(kret));
knot_strerror(ret));
goto fail;
}
......@@ -419,10 +418,8 @@ void zonefile_close(zloader_t *loader)
return;
}
zs_scanner_free(loader->scanner);
zs_deinit(&loader->scanner);
free(loader->source);
free(loader->origin);
free(loader->creator);
}
......
......@@ -47,11 +47,10 @@ typedef struct zcreator {
*/
typedef struct zloader {
char *source; /*!< Zone source file. */
char *origin; /*!< Zone's origin string. */
bool semantic_checks; /*!< Do semantic checks. */
err_handler_t *err_handler; /*!< Semantic checks error handler. */
zs_scanner_t *scanner; /*!< Zone scanner. */
zcreator_t *creator; /*!< Loader context. */
zs_scanner_t scanner; /*!< Zone scanner. */
} zloader_t;
/*!
......
......@@ -157,8 +157,9 @@ static bool dname_isvalid(const char *lp)
/* This is probably redundant, but should be a bit faster so let's keep it. */
static int parse_full_rr(zs_scanner_t *s, const char* lp)
{
if (zs_scanner_parse(s, lp, lp + strlen(lp), true) < 0) {
ERR("invalid record (%s)\n", zs_strerror(s->error_code));
if (zs_set_input_string(s, lp, strlen(lp)) != 0 ||
zs_parse_all(s) != 0) {
ERR("invalid record (%s)\n", zs_strerror(s->error.code));
return KNOT_EPARSEFAIL;
}
......@@ -294,8 +295,9 @@ static int parse_partial_rr(zs_scanner_t *s, const char *lp, unsigned flags)
if (rr == NULL) {
return KNOT_ENOMEM;
}
if (zs_scanner_parse(s, rr, rr + strlen(rr), true) < 0) {
ERR("invalid rdata (%s)\n", zs_strerror(s->error_code));
if (zs_set_input_string(s, rr, strlen(rr)) != 0 ||
zs_parse_all(s) != 0) {
ERR("invalid rdata (%s)\n", zs_strerror(s->error.code));
return KNOT_EPARSEFAIL;
}
free(rr);
......@@ -607,18 +609,18 @@ int cmd_add(const char* lp, knsupdate_params_t *params)
{
DBG("%s: lp='%s'\n", __func__, lp);
if (parse_full_rr(params->parser, lp) != KNOT_EOK) {
if (parse_full_rr(&params->parser, lp) != KNOT_EOK) {
return KNOT_EPARSEFAIL;
}
return rr_list_append(params->parser, &params->update_list, &params->mm);
return rr_list_append(&params->parser, &params->update_list, &params->mm);
}
int cmd_del(const char* lp, knsupdate_params_t *params)
{
DBG("%s: lp='%s'\n", __func__, lp);
zs_scanner_t *rrp = params->parser;
zs_scanner_t *rrp = &params->parser;
int ret = parse_partial_rr(rrp, lp, PARSE_NODEFAULT);
if (ret != KNOT_EOK) {
return ret;
......@@ -654,7 +656,7 @@ int cmd_class(const char* lp, knsupdate_params_t *params)
}
params->class_num = cls;
params->parser->default_class = params->class_num;
params->parser.default_class = params->class_num;
return KNOT_EOK;
}
......@@ -687,7 +689,7 @@ int cmd_nxdomain(const char *lp, knsupdate_params_t *params)
{
DBG("%s: lp='%s'\n", __func__, lp);
zs_scanner_t *s = params->parser;
zs_scanner_t *s = &params->parser;
int ret = parse_partial_rr(s, lp, PARSE_NODEFAULT | PARSE_NAMEONLY);
if (ret != KNOT_EOK) {
return ret;
......@@ -703,7 +705,7 @@ int cmd_yxdomain(const char *lp, knsupdate_params_t *params)
{
DBG("%s: lp='%s'\n", __func__, lp);
zs_scanner_t *s = params->parser;
zs_scanner_t *s = &params->parser;
int ret = parse_partial_rr(s, lp, PARSE_NODEFAULT | PARSE_NAMEONLY);
if (ret != KNOT_EOK) {
return ret;
......@@ -719,7 +721,7 @@ int cmd_nxrrset(const char *lp, knsupdate_params_t *params)
{
DBG("%s: lp='%s'\n", __func__, lp);
zs_scanner_t *s = params->parser;
zs_scanner_t *s = &params->parser;
int ret = parse_partial_rr(s, lp, PARSE_NOTTL);
if (ret != KNOT_EOK) {
return ret;
......@@ -741,7 +743,7 @@ int cmd_yxrrset(const char *lp, knsupdate_params_t *params)
{
DBG("%s: lp='%s'\n", __func__, lp);
zs_scanner_t *s = params->parser;
zs_scanner_t *s = &params->parser;
int ret = parse_partial_rr(s, lp, PARSE_NOTTL);
if (ret != KNOT_EOK) {
return ret;
......
......@@ -57,7 +57,7 @@ static const style_t DEFAULT_STYLE_NSUPDATE = {
};
static void parse_err(zs_scanner_t *s) {
ERR("failed to parse RR: %s\n", zs_strerror(s->error_code));
ERR("failed to parse RR: %s\n", zs_strerror(s->error.code));
}
static int parser_set_default(zs_scanner_t *s, const char *fmt, ...)
......@@ -74,7 +74,8 @@ static int parser_set_default(zs_scanner_t *s, const char *fmt, ...)
}
/* Buffer must contain newline */
if (zs_scanner_parse(s, buf, buf + n, true) < 0) {
if (zs_set_input_string(s, buf, n) != 0 ||
zs_parse_all(s) != 0) {
return KNOT_EPARSEFAIL;
}
......@@ -109,10 +110,11 @@ static int knsupdate_init(knsupdate_params_t *params)
params->zone = strdup(".");
/* Initialize RR parser. */
params->parser = zs_scanner_create(".", params->class_num, 0,
NULL, parse_err, NULL);
if (!params->parser)
if (zs_init(&params->parser, ".", params->class_num, 0) != 0 ||
zs_set_processing(&params->parser, NULL, parse_err, NULL) != 0) {
zs_deinit(&params->parser);
return KNOT_ENOMEM;
}
/* Default style. */
params->style = DEFAULT_STYLE_NSUPDATE;
......@@ -139,7 +141,7 @@ void knsupdate_clean(knsupdate_params_t *params)
srv_info_free(params->server);
srv_info_free(params->srcif);
free(params->zone);
zs_scanner_free(params->parser);
zs_deinit(&params->parser);
knot_pkt_free(&params->query);
knot_pkt_free(&params->answer);
knot_tsig_key_deinit(&params->tsig_key);
......@@ -283,7 +285,7 @@ int knsupdate_parse(knsupdate_params_t *params, int argc, char *argv[])
int knsupdate_set_ttl(knsupdate_params_t *params, const uint32_t ttl)
{
int ret = parser_set_default(params->parser, "$TTL %u\n", ttl);
int ret = parser_set_default(&params->parser, "$TTL %u\n", ttl);
if (ret == KNOT_EOK) {
params->ttl = ttl;
} else {
......@@ -296,7 +298,7 @@ int knsupdate_set_origin(knsupdate_params_t *params, const char *origin)
{
char *fqdn = get_fqd_name(origin);
int ret = parser_set_default(params->parser, "$ORIGIN %s\n", fqdn);
int ret = parser_set_default(&params->parser, "$ORIGIN %s\n", fqdn);
free(fqdn);
......
......@@ -67,7 +67,7 @@ typedef struct {
/*!< Current zone. */
char *zone;
/*!< RR parser. */
zs_scanner_t *parser;
zs_scanner_t parser;
/*!< Current packet. */
knot_pkt_t *query;
/*!< Current response. */
......
......@@ -27,20 +27,20 @@ typedef struct {
#define ERR_ITEM(code, text) { code, text, #code }
static const err_table_t err_msgs[] = {
ERR_ITEM( ZS_OK, "ok" ),
ERR_ITEM( ZS_SYSTEM,
"system error" ),
ERR_ITEM( ZS_OK,
"ok" ),
ERR_ITEM( ZS_EINVAL,
"invalid parameter" ),
ERR_ITEM( ZS_ENOMEM,
"not enough memory" ),
ERR_ITEM( ZS_FILE_OPEN,
"file open error" ),
ERR_ITEM( ZS_FILE_INVALID,
"invalid file" ),
ERR_ITEM( ZS_FILE_PATH,
"file path error" ),
ERR_ITEM( ZS_FILE_FSTAT,
"fstat error" ),
ERR_ITEM( ZS_FILE_DIR,
"not zone file but directory" ),
ERR_ITEM( ZS_FILE_MMAP,
"file mmap error" ),
"file memory mapping error" ),
ERR_ITEM( ZS_DOS_NEWLINE,
"unsupported CRLF newline, remove CR bytes" ),
ERR_ITEM( ZS_UNCOVERED_STATE,
......
......@@ -26,12 +26,11 @@
enum err_codes {
ZS_OK = 0,
ZS_SYSTEM = -1000,
ZS_EINVAL = -1000,
ZS_ENOMEM,
ZS_FILE_OPEN,
ZS_FILE_INVALID,
ZS_FILE_PATH,
ZS_FILE_FSTAT,
ZS_FILE_DIR,
ZS_FILE_MMAP,
ZS_DOS_NEWLINE,
ZS_UNCOVERED_STATE,
......
This diff is collapsed.
This diff is collapsed.
......@@ -27,6 +27,7 @@
#pragma once
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "zscanner/error.h"
......@@ -83,6 +84,15 @@ typedef struct {
int8_t lat_sign, long_sign, alt_sign;
} loc_t;
/*! \brief Scanner states describing the result. */
typedef enum {
ZS_STATE_DATA, /*!< A record parsed. */
ZS_STATE_ERROR, /*!< An error occured. */
ZS_STATE_INCLUDE, /*!< An include directive parsed. */
ZS_STATE_EOF, /*!< The end of the current input reached. */
ZS_STATE_STOP /*!< Finished parsing. */
} zs_state_t;
/*!
* \brief Context structure for zone scanner.
*
......@@ -128,7 +138,9 @@ struct scanner {
/*! Auxiliary buffer for data storing. */
uint8_t buffer[MAX_RDATA_LENGTH];
/*! Auxiliary buffer for current included file name. */
char include_filename[MAX_RDATA_LENGTH + 1];
char include_filename[MAX_RDATA_LENGTH];
/*! Absolute path for relative includes. */
char *path;
/*! Auxiliary array of bitmap window blocks. */
window_t windows[BITMAP_WINDOWS];
......@@ -166,27 +178,34 @@ struct scanner {
/*! Value of the current default ttl (TTL directive sets this). */
uint32_t default_ttl;
/*! Callback function for correct zone record. */
void (*process_record)(zs_scanner_t *);
/*! Callback function for wrong situations. */
void (*process_error)(zs_scanner_t *);
/*! Arbitrary data useful inside callback functions. */
void *data;
/*! The current processing state. */
zs_state_t state;
/*! Absolute path for relative includes. */
char *path;
/*! Zone data line counter. */
uint64_t line_counter;
/*! Last occured error/warning code. */
int error_code;
/*! Errors/warnings counter. */
uint64_t error_counter;
/*!
* Indicates serious warning which is considered as an error and
* forces zone processing to stop.
*/
bool stop;
/*! Processing callbacks and auxiliary data. */
struct {
/*! Automatic zone processing using record/error callbacks. */
bool automatic;
/*! Callback function for correct zone record. */
void (*record)(zs_scanner_t *);
/*! Callback function for wrong situations. */
void (*error)(zs_scanner_t *);
/*! Arbitrary data useful inside callback functions. */
void *data;
} process;
/*! Input parameters. */
struct {
/*! Start of the block. */
const char *start;
/*! Current parser position. */
const char *current;
/*! End of the block. */
const char *end;
/*! Indication for the final block parsing. */
bool eof;
} input;
/*! File input parameters. */
struct {
/*! Zone file name. */
char *name;
......@@ -194,6 +213,18 @@ struct scanner {
int descriptor;
} file;
struct {
/*! Last occured error/warning code. */
int code;
/*! Error/warning counter. */
uint64_t counter;
/*! Indicates serious error - parsing cannot continue. */
bool fatal;
} error;
/*! Zone data line counter. */
uint64_t line_counter;
/*! Length of the current record owner. */
uint32_t r_owner_length;
/*!
......@@ -227,70 +258,119 @@ struct scanner {
};
/*!
* \brief Creates zone scanner structure.
* \brief Initializes the scanner context.
*
* \note Error code is stored in the scanner context.
*
* \param scanner Scanner context.
* \param origin Initial zone origin.
* \param rclass Zone class value.
* \param ttl Initial ttl value.
*
* \retval 0 if success.
* \retval -1 if error.
*/
int zs_init(
zs_scanner_t *scanner,
const char *origin,
const uint16_t rclass,
const uint32_t ttl
);
/*!
* \brief Deinitializes the scanner context.
*
* \param scanner Scanner context.
*/
void zs_deinit(
zs_scanner_t *scanner
);
/*!
* \brief Sets the scanner to parse a zone data string.
*
* \param origin Initial zone origin.
* \param rclass Zone class value.
* \param ttl Initial ttl value.
* \param process_record Processing callback function.
* \param process_error Error callback function.
* \param data Arbitrary data useful in callback functions.
* \note Error code is stored in the scanner context.
*
* \retval scanner if success.
* \retval NULL if error.
* \param scanner Scanner context.
* \param input Input zone data string to parse.
* \param size Size of the input string.
*
* \retval 0 if success.
* \retval -1 if error.
*/
zs_scanner_t* zs_scanner_create(const char *origin,