lua: most changes needed for knot 2.7

When at it, switch to generating the libzscanner bindings.
parent 07d183cb
......@@ -22,15 +22,28 @@ typedef struct {
uint16_t compress_ptr[16];
} knot_rrinfo_t;
typedef unsigned char knot_dname_t;
typedef unsigned char knot_rdata_t;
typedef struct knot_rdataset knot_rdataset_t;
struct knot_rdataset {
typedef struct {
uint16_t len;
uint8_t data[];
} knot_rdata_t;
typedef struct {
uint16_t rr_count;
knot_rdata_t *data;
};
typedef struct knot_rrset knot_rrset_t;
} knot_rdataset_t;
typedef struct {
knot_dname_t *_owner;
uint32_t _ttl;
uint16_t type;
uint16_t rclass;
knot_rdataset_t rrs;
void *additional;
} knot_rrset_t;
typedef struct knot_pkt knot_pkt_t;
typedef struct {
struct knot_pkt *pkt;
uint8_t *ptr[15];
} knot_edns_options_t;
typedef struct {
knot_pkt_t *pkt;
uint16_t pos;
uint16_t count;
} knot_pktsection_t;
......@@ -54,6 +67,7 @@ struct knot_pkt {
uint16_t flags;
knot_rrset_t *opt_rr;
knot_rrset_t *tsig_rr;
knot_edns_options_t *edns_opts;
struct {
uint8_t *pos;
size_t len;
......@@ -66,7 +80,6 @@ struct knot_pkt {
knot_mm_t mm;
knot_compr_t compr;
};
typedef struct knot_pkt knot_pkt_t;
typedef struct {
void *root;
struct knot_mm *pool;
......@@ -201,13 +214,9 @@ struct kr_cache {
typedef int32_t (*kr_stale_cb)(int32_t ttl, const knot_dname_t *owner, uint16_t type,
const struct kr_query *qry);
struct knot_rrset {
knot_dname_t *_owner;
uint16_t type;
uint16_t rclass;
knot_rdataset_t rrs;
void *additional;
};
void kr_rrset_init(knot_rrset_t *rrset, knot_dname_t *owner,
uint16_t type, uint16_t rclass, uint32_t ttl);
struct kr_nsrep {
unsigned int score;
unsigned int reputation;
......@@ -251,31 +260,20 @@ knot_dname_t *knot_dname_copy(const knot_dname_t *, knot_mm_t *);
knot_dname_t *knot_dname_from_str(uint8_t *, const char *, size_t);
_Bool knot_dname_is_equal(const knot_dname_t *, const knot_dname_t *);
_Bool knot_dname_is_sub(const knot_dname_t *, const knot_dname_t *);
int knot_dname_labels(const uint8_t *, const uint8_t *);
int knot_dname_size(const knot_dname_t *);
size_t knot_dname_labels(const uint8_t *, const uint8_t *);
size_t knot_dname_size(const knot_dname_t *);
char *knot_dname_to_str(char *, const knot_dname_t *, size_t);
size_t knot_rdata_array_size(uint16_t);
knot_rdata_t *knot_rdataset_at(const knot_rdataset_t *, size_t);
knot_rdata_t *knot_rdataset_at(const knot_rdataset_t *, uint16_t);
int knot_rdataset_merge(knot_rdataset_t *, const knot_rdataset_t *, knot_mm_t *);
int knot_rrset_add_rdata(knot_rrset_t *, const uint8_t *, const uint16_t, const uint32_t, knot_mm_t *);
void knot_rrset_init_empty(knot_rrset_t *);
uint32_t knot_rrset_ttl(const knot_rrset_t *);
int knot_rrset_add_rdata(knot_rrset_t *, const uint8_t *, uint16_t, knot_mm_t *);
int knot_rrset_txt_dump(const knot_rrset_t *, char **, size_t *, const knot_dump_style_t *);
int knot_rrset_txt_dump_data(const knot_rrset_t *, const size_t, char *, const size_t, const knot_dump_style_t *);
size_t knot_rrset_size(const knot_rrset_t *);
uint16_t knot_rrsig_type_covered(const knot_rdataset_t *, size_t);
uint32_t knot_rrsig_sig_expiration(const knot_rdataset_t *, size_t);
uint32_t knot_rrsig_sig_inception(const knot_rdataset_t *, size_t);
const knot_dname_t *knot_pkt_qname(const knot_pkt_t *);
uint16_t knot_pkt_qtype(const knot_pkt_t *);
uint16_t knot_pkt_qclass(const knot_pkt_t *);
int knot_pkt_begin(knot_pkt_t *, knot_section_t);
int knot_pkt_put_question(knot_pkt_t *, const knot_dname_t *, uint16_t, uint16_t);
int knot_pkt_put(knot_pkt_t *, uint16_t, const knot_rrset_t *, uint16_t);
const knot_rrset_t *knot_pkt_rr(const knot_pktsection_t *, uint16_t);
const knot_pktsection_t *knot_pkt_section(const knot_pkt_t *, knot_section_t);
int knot_pkt_put_rotate(knot_pkt_t *, uint16_t, const knot_rrset_t *, uint16_t, uint16_t);
knot_pkt_t *knot_pkt_new(void *, uint16_t, knot_mm_t *);
void knot_pkt_free(knot_pkt_t **);
void knot_pkt_free(knot_pkt_t *);
int knot_pkt_parse(knot_pkt_t *, unsigned int);
struct kr_rplan *kr_resolve_plan(struct kr_request *);
knot_mm_t *kr_resolve_pool(struct kr_request *);
......@@ -290,6 +288,10 @@ void kr_pkt_make_auth_header(knot_pkt_t *);
int kr_pkt_put(knot_pkt_t *, const knot_dname_t *, uint32_t, uint16_t, uint16_t, const uint8_t *, uint16_t);
int kr_pkt_recycle(knot_pkt_t *);
int kr_pkt_clear_payload(knot_pkt_t *);
uint16_t kr_pkt_qclass(const knot_pkt_t *);
uint16_t kr_pkt_qtype(const knot_pkt_t *);
uint32_t kr_rrsig_sig_inception(const knot_rdataset_t *, size_t);
uint32_t kr_rrsig_sig_expiration(const knot_rdataset_t *, size_t);
const char *kr_inaddr(const struct sockaddr *);
int kr_inaddr_family(const struct sockaddr *);
int kr_inaddr_len(const struct sockaddr *);
......
......@@ -46,13 +46,22 @@ typedef void (*trace_callback_f)(struct kr_request *);
knot_dname_t
knot_rdata_t
knot_rdataset_t
struct knot_rdataset
knot_rrset_t
EOF
genResType() {
echo "$1" | ./scripts/gen-cdefs.sh libkres types
}
# No simple way to fixup this rename in ./kres.lua AFAIK.
genResType "knot_rrset_t" | sed 's/\<owner\>/_owner/; s/\<ttl\>/_ttl/'
./scripts/gen-cdefs.sh libkres types <<-EOF
knot_pkt_t
knot_edns_options_t
knot_pktsection_t
struct knot_compr
knot_compr_t
struct knot_pkt
knot_pkt_t
# generics
map_t
# libkres
......@@ -73,14 +82,10 @@ EOF
printf "
typedef int32_t (*kr_stale_cb)(int32_t ttl, const knot_dname_t *owner, uint16_t type,
const struct kr_query *qry);
"
genResType() {
echo "$1" | ./scripts/gen-cdefs.sh libkres types
}
# No simple way to fixup this rename in ./kres.lua AFAIK.
genResType "struct knot_rrset" | sed 's/\<owner\>/_owner/'
void kr_rrset_init(knot_rrset_t *rrset, knot_dname_t *owner,
uint16_t type, uint16_t rclass, uint32_t ttl);
"
## Some definitions would need too many deps, so shorten them.
......@@ -105,26 +110,16 @@ printf "\tchar _stub[];\n};\n"
knot_dname_size
knot_dname_to_str
# Resource records
knot_rdata_array_size
knot_rdataset_at
knot_rdataset_merge
knot_rrset_add_rdata
knot_rrset_init_empty
knot_rrset_txt_dump
knot_rrset_txt_dump_data
knot_rrset_size
knot_rrsig_type_covered
knot_rrsig_sig_expiration
knot_rrsig_sig_inception
# Packet
knot_pkt_qname
knot_pkt_qtype
knot_pkt_qclass
knot_pkt_begin
knot_pkt_put_question
knot_pkt_put
knot_pkt_rr
knot_pkt_section
knot_pkt_put_rotate
knot_pkt_new
knot_pkt_free
knot_pkt_parse
......@@ -149,6 +144,10 @@ EOF
kr_pkt_put
kr_pkt_recycle
kr_pkt_clear_payload
kr_pkt_qclass
kr_pkt_qtype
kr_rrsig_sig_inception
kr_rrsig_sig_expiration
kr_inaddr
kr_inaddr_family
kr_inaddr_len
......
......@@ -340,12 +340,13 @@ local knot_rrset_pt = ffi.typeof('knot_rrset_t *')
local knot_rrset_t = ffi.typeof('knot_rrset_t')
ffi.metatype( knot_rrset_t, {
-- Create a new empty RR set object with an allocated owner and a destructor
__new = function (ct, owner, rrtype, rrclass)
__new = function (ct, owner, rrtype, rrclass, ttl)
local rr = ffi.new(ct)
knot.knot_rrset_init_empty(rr)
rr._owner = owner and knot.knot_dname_copy(owner, nil)
rr.type = rrtype or 0
rr.rclass = rrclass or const_class.IN
C.kr_rrset_init(rr,
owner and knot.knot_dname_copy(owner, nil),
rrtype or 0,
rrclass or const_class.IN,
ttl or 0)
return ffi.gc(rr, rrset_free)
end,
-- beware: `owner` and `rdata` are typed as a plain lua strings
......@@ -361,7 +362,7 @@ ffi.metatype( knot_rrset_t, {
end,
ttl = function(rr)
assert(ffi.istype(knot_rrset_t, rr))
return tonumber(rr.ttl)
return tonumber(rr._ttl)
end,
class = function(rr, val)
assert(ffi.istype(knot_rrset_t, rr))
......@@ -477,14 +478,19 @@ local function pkt_bit(pkt, byteoff, bitmask, val)
return (bit.band(pkt.wire[byteoff], bitmask) ~= 0)
end
local function knot_pkt_rr(section, i)
assert(section and ffi.istype('knot_pktsection_t', section))
return section.pkt.rr + section.pos + i;
end
-- Helpers for converting packet to text
local function section_tostring(pkt, section_id)
local data = {}
local section = knot.knot_pkt_section(pkt, section_id)
local section = pkt.sections[section_id]
if section.count > 0 then
table.insert(data, string.format('\n;; %s\n', const_section_str[section_id]))
for j = 0, section.count - 1 do
local rrset = knot.knot_pkt_rr(section, j)
local rrset = knot_pkt_rr(section, j)
local rrtype = rrset.type
if rrtype ~= const_type.OPT and rrtype ~= const_type.TSIG then
table.insert(data, rrset:txt_dump())
......@@ -581,23 +587,24 @@ ffi.metatype( knot_pkt_t, {
-- Question
qname = function(pkt)
assert(ffi.istype(knot_pkt_t, pkt))
local qname = knot.knot_pkt_qname(pkt)
return dname2wire(qname)
-- inlined knot_pkt_qname(), basically
if pkt == nil or pkt.qname_size == 0 then return nil end
return ffi.string(pkt.wire + 12, pkt.qname_size)
end,
qclass = function(pkt)
assert(ffi.istype(knot_pkt_t, pkt))
return knot.knot_pkt_qclass(pkt)
return C.kr_pkt_qclass(pkt)
end,
qtype = function(pkt)
assert(ffi.istype(knot_pkt_t, pkt))
return knot.knot_pkt_qtype(pkt)
return C.kr_pkt_qtype(pkt)
end,
rrsets = function (pkt, section_id)
assert(ffi.istype(knot_pkt_t, pkt))
local records = {}
local section = knot.knot_pkt_section(pkt, section_id)
local section = pkt.sections[section_id]
for i = 1, section.count do
local rrset = knot.knot_pkt_rr(section, i - 1)
local rrset = knot_pkt_rr(section, i - 1)
table.insert(records, ffi.cast(knot_rrset_pt, rrset))
end
return records
......@@ -605,9 +612,9 @@ ffi.metatype( knot_pkt_t, {
section = function (pkt, section_id)
assert(ffi.istype(knot_pkt_t, pkt))
local records = {}
local section = knot.knot_pkt_section(pkt, section_id)
local section = pkt.sections[section_id]
for i = 1, section.count do
local rrset = knot.knot_pkt_rr(section, i - 1)
local rrset = knot_pkt_rr(section, i - 1)
for k = 1, rrset:rdcount() do
table.insert(records, rrset:get(k - 1))
end
......@@ -633,7 +640,7 @@ ffi.metatype( knot_pkt_t, {
put_rr = function (pkt, rr)
assert(ffi.istype(knot_pkt_t, pkt))
assert(ffi.istype(knot_rrset_t, rr))
local ret = C.knot_pkt_put(pkt, 0, rr, 0)
local ret = C.knot_pkt_put_rotate(pkt, 0, rr, 0, 0)
if ret ~= 0 then return nil, knot_error_t(ret) end
return true
end,
......@@ -915,6 +922,8 @@ kres = {
return ffi.string(addr_buf, C.kr_family_len(family))
end,
context = function () return ffi.cast('struct kr_context *', __engine) end,
knot_pkt_rr = knot_pkt_rr,
}
return kres
......@@ -4,6 +4,9 @@
local ffi = require('ffi')
local libzscanner = ffi.load(libzscanner_SONAME)
-- FIXME: strip the C comments, probably
-- Note: struct zs_scanner::state uses int directly instead of typedefed enum,
-- and the corresponding struct zs_state is defined in a different way.
ffi.cdef[[
void free(void *ptr);
void *realloc(void *ptr, size_t size);
......@@ -13,25 +16,28 @@ void *realloc(void *ptr, size_t size);
*/
enum {
MAX_RDATA_LENGTH = 65535,
MAX_ITEM_LENGTH = 255,
MAX_DNAME_LENGTH = 255,
MAX_LABEL_LENGTH = 63,
MAX_RDATA_ITEMS = 64,
BITMAP_WINDOWS = 256,
INET4_ADDR_LENGTH = 4,
INET6_ADDR_LENGTH = 16,
RAGEL_STACK_SIZE = 16,
ZS_MAX_RDATA_LENGTH =65535,
ZS_MAX_DNAME_LENGTH =255,
ZS_MAX_LABEL_LENGTH =63,
ZS_INET4_ADDR_LENGTH =4,
ZS_INET6_ADDR_LENGTH =16,
ZS_BITMAP_WINDOWS =256,
ZS_RAGEL_STACK_SIZE =16,
};
typedef struct {
uint8_t bitmap[32];
uint8_t length;
} window_t;
} zs_win_t;
/*! \brief Auxiliary structure for storing one APL record (see RFC3123). */
typedef struct {
uint8_t excl_flag;
uint16_t addr_family;
uint8_t prefix_length;
} apl_t;
} zs_apl_t;
/*! \brief Auxiliary structure for storing LOC information (see RFC1876). */
typedef struct {
uint32_t d1, d2;
uint32_t m1, m2;
......@@ -39,93 +45,310 @@ typedef struct {
uint32_t alt;
uint64_t siz, hp, vp;
int8_t lat_sign, long_sign, alt_sign;
} loc_t;
} zs_loc_t;
/*! \brief Scanner states describing the result. */
typedef struct zs_state {
static const int NONE = 0;
static const int DATA = 1;
static const int ERROR = 2;
static const int INCLUDE = 3;
static const int EOF = 4;
static const int STOP = 5;
static const int NONE = 0; /*!< Initial state (no data). */
static const int DATA = 1; /*!< A record parsed. */
static const int ERROR = 2; /*!< An error occurred. */
static const int INCLUDE = 3; /*!< An include directive (see include_filename, buffer). */
static const int EOF = 4; /*!< The end of the current input reached. */
static const int STOP = 5; /*!< Early stop (possibly set from a callback). */
} zs_state_t;
typedef struct scanner {
/*!
* \brief Context structure for zone scanner.
*
* This structure contains following items:
* - Copies of Ragel internal variables. The scanner can be called many times
* on smaller parts of zone file/memory. So it is necessary to preserve
* internal values between subsequent scanner callings.
* - Auxiliary variables which are used during processing zone data.
* - Pointers to callback functions and pointer to any arbitrary data which
* can be used in callback functions.
* - Zone file and error information.
* - Output variables (r_ prefix) containing all parts of zone record. These
* data are useful during processing via callback function.
*/
typedef struct zs_scanner zs_scanner_t; // Forward declaration due to arguments.
struct zs_scanner {
/*! Current state (Ragel internals). */
int cs;
/*! Stack top (Ragel internals). */
int top;
int stack[RAGEL_STACK_SIZE];
/*! Call stack (Ragel internals). */
int stack[ZS_RAGEL_STACK_SIZE];
/*! Indicates whether current record is multiline. */
bool multiline;
/*! Auxiliary number for all numeric operations. */
uint64_t number64;
/*! Auxiliary variable for time and other numeric operations. */
uint64_t number64_tmp;
/*! Auxiliary variable for float numeric operations. */
uint32_t decimals;
/*! Auxiliary variable for float numeric operations. */
uint32_t decimal_counter;
/*! Auxiliary variable for item length (label, base64, ...). */
uint32_t item_length;
/*! Auxiliary index for item length position in array. */
uint32_t item_length_position;
/*! Auxiliary pointer to item length. */
uint8_t *item_length_location;
/*! Auxiliary buffer length. Is zero if no comment after a valid record. */
uint32_t buffer_length;
uint8_t buffer[MAX_RDATA_LENGTH];
char include_filename[MAX_RDATA_LENGTH];
/*! Auxiliary buffer. Contains a comment after a valid record. */
uint8_t buffer[ZS_MAX_RDATA_LENGTH];
/*! Auxiliary buffer for current included file name. */
char include_filename[ZS_MAX_RDATA_LENGTH];
/*! Absolute path for relative includes. */
char *path;
window_t windows[BITMAP_WINDOWS];
/*! Auxiliary array of bitmap window blocks. */
zs_win_t windows[ZS_BITMAP_WINDOWS];
/*! Last window block which is used (-1 means no window). */
int16_t last_window;
apl_t apl;
loc_t loc;
/*! Auxiliary apl structure. */
zs_apl_t apl;
/*! Auxiliary loc structure. */
zs_loc_t loc;
/*! Auxiliary IP address storage. */
uint8_t addr[ZS_INET6_ADDR_LENGTH];
/*! Allow text strings longer than 255 characters. */
bool long_string;
/*! Pointer to the actual dname storage (origin/owner/rdata). */
uint8_t *dname;
/*! Pointer to the actual dname length storage. */
uint32_t *dname_length;
/*!
* Temporary dname length which is copied to dname_length after
* dname processing.
*/
uint32_t dname_tmp_length;
/*! Position of the last free r_data byte. */
uint32_t r_data_tail;
/*! Length of the current origin. */
uint32_t zone_origin_length;
uint8_t zone_origin[MAX_DNAME_LENGTH + MAX_LABEL_LENGTH];
/*!
* Wire format of the current origin (ORIGIN directive sets this).
*
* \note Maximal dname length check is after each valid label.
*/
uint8_t zone_origin[ZS_MAX_DNAME_LENGTH + ZS_MAX_LABEL_LENGTH];
/*! Value of the default class. */
uint16_t default_class;
/*! Value of the current default ttl (TTL directive sets this). */
uint32_t default_ttl;
/*! The current processing state. */
int state;
/*! Processing callbacks and auxiliary data. */
struct {
/*! Automatic zone processing using record/error callbacks. */
bool automatic;
void (*record)(struct zs_scanner *);
void (*error)(struct zs_scanner *);
/*! 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;
/*! Indication of being mmap()-ed (malloc()-ed otherwise). */
bool mmaped;
} input;
/*! File input parameters. */
struct {
/*! Zone file name. */
char *name;
/*!< File descriptor. */
int descriptor;
} file;
struct {
/*! Last occurred 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;
uint8_t r_owner[MAX_DNAME_LENGTH + MAX_LABEL_LENGTH];
/*!
* Owner of the current record.
*
* \note Maximal dname length check is after each valid label.
*/
uint8_t r_owner[ZS_MAX_DNAME_LENGTH + ZS_MAX_LABEL_LENGTH];
/*! Class of the current record. */
uint16_t r_class;
/*! TTL of the current record. */
uint32_t r_ttl;
/*! Type of the current record data. */
uint16_t r_type;
/*! Length of the current rdata. */
uint32_t r_data_length;
uint8_t r_data[MAX_RDATA_LENGTH];
} zs_scanner_t;
/*! Current rdata. */
uint8_t r_data[ZS_MAX_RDATA_LENGTH];
/*
* Function signatures
/*
* Example: a. IN 60 MX 1 b. ; A comment
*
* r_owner_length = 3
* r_owner = 016100
* r_class = 1
* r_ttl = 60
* r_type = 15
* r_data_length = 5
* r_data = 0001016200
* buffer_length = 11
* buffer = " A comment"
*/
};
/*!
* \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.
*
* \note Error code is stored in the scanner context.
*
* \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.
*/
int zs_set_input_string(
zs_scanner_t *scanner,
const char *input,
size_t size
);
/*!
* \brief Sets the scanner to parse a zone file..
*
* \note Error code is stored in the scanner context.
*
* \param scanner Scanner context.
* \param file_name Name of the file to parse.
*
* \retval 0 if success.
* \retval -1 if error.
*/
int zs_set_input_file(
zs_scanner_t *scanner,
const char *file_name
);
/*!
* \brief Sets the scanner processing callbacks for automatic processing.
*
* \note Error code is stored in the scanner context.
*
* \param scanner Scanner context.
* \param process_record Processing callback function (may be NULL).
* \param process_error Error callback function (may be NULL).
* \param data Arbitrary data useful in callback functions.
*
* \retval 0 if success.
* \retval -1 if error.
*/
int zs_set_processing(
zs_scanner_t *scanner,
void (*process_record)(zs_scanner_t *),
void (*process_error)(zs_scanner_t *),
void *data
);
/*!
* \brief Parses one record from the input.
*
* The following processing should be based on the scanner->state.
*
* \note Error code and other information are stored in the scanner context.
*
* \param scanner Scanner context.
*
* \retval 0 if success.
* \retval -1 if error.
*/
int zs_parse_record(
zs_scanner_t *scanner
);
/*!
* \brief Launches automatic parsing of the whole input.
*
* For each correctly recognized record, the record callback is executed.
* If any syntax error occurs, the error callback is executed.
*
* \note Error code and other information are stored in the scanner context.