267 lines
9.7 KiB
C
267 lines
9.7 KiB
C
/*
|
|
* ixfr.h -- generating IXFR responses.
|
|
*
|
|
* Copyright (c) 2021, NLnet Labs. All rights reserved.
|
|
*
|
|
* See LICENSE for the license.
|
|
*
|
|
*/
|
|
|
|
#ifndef IXFR_H
|
|
#define IXFR_H
|
|
struct nsd;
|
|
#include "query.h"
|
|
#include "rbtree.h"
|
|
struct ixfr_data;
|
|
struct zone;
|
|
struct buffer;
|
|
struct region;
|
|
|
|
/* default for number of ixfr versions in files */
|
|
#define IXFR_NUMBER_DEFAULT 5 /* number of versions */
|
|
/* default for IXFR storage */
|
|
#define IXFR_SIZE_DEFAULT 1048576 /* in bytes, 1M */
|
|
|
|
/* data structure that stores IXFR contents for a zone. */
|
|
struct zone_ixfr {
|
|
/* Items are of type ixfr_data. The key is old_serial.
|
|
* So it can be looked up on an incoming IXFR. They are sorted
|
|
* by old_serial, so the looked up and next are the versions needed.
|
|
* Tree of ixfr data for versions */
|
|
struct rbtree* data;
|
|
/* total size stored at this time, in bytes,
|
|
* sum of sizes of the ixfr data elements */
|
|
size_t total_size;
|
|
/* the oldest serial number in the tree, searchable by old_serial */
|
|
uint32_t oldest_serial;
|
|
/* the newest serial number in the tree, that is searchable in the
|
|
* tree, so it is the old_serial of the newest data entry, that
|
|
* has an even newer new_serial of that entry */
|
|
uint32_t newest_serial;
|
|
};
|
|
|
|
/* Data structure that stores one IXFR.
|
|
* The RRs are stored in uncompressed wireformat, that means
|
|
* an uncompressed domain name, type, class, TTL, rdatalen,
|
|
* uncompressed rdata in wireformat.
|
|
*
|
|
* The data structure is formatted like this so that making an IXFR
|
|
* that moves across several versions can be done by collating the
|
|
* pieces precisely from the versions involved. In particular, for
|
|
* an IXFR from olddata to newdata, for a combined output:
|
|
* newdata.newsoa olddata.oldsoa olddata.del olddata.add
|
|
* newdata.del newdata.add
|
|
* in sequence should produce a valid, non-condensed, IXFR with multiple
|
|
* versions inside.
|
|
*/
|
|
struct ixfr_data {
|
|
/* Node in the rbtree. Key is oldserial */
|
|
struct rbnode node;
|
|
/* from what serial the IXFR starts from, the 'old' serial */
|
|
uint32_t oldserial;
|
|
/* where to IXFR goes to, the 'new' serial */
|
|
uint32_t newserial;
|
|
/* the new SOA record, with newserial */
|
|
uint8_t* newsoa;
|
|
/* byte length of the uncompressed wireformat RR in newsoa */
|
|
size_t newsoa_len;
|
|
/* the old SOA record, with oldserial */
|
|
uint8_t* oldsoa;
|
|
/* byte length of the uncompressed wireformat RR in oldsoa*/
|
|
size_t oldsoa_len;
|
|
/* the deleted RRs, ends with the newserial SOA record.
|
|
* if the ixfr is collated out multiple versions, then
|
|
* this deleted RRs section contains several add and del sections
|
|
* for the older versions, and ends with the last del section,
|
|
* and the SOA record with the newserial.
|
|
* That is everything except the final add section for newserial. */
|
|
uint8_t* del;
|
|
/* byte length of the uncompressed wireformat RRs in del */
|
|
size_t del_len;
|
|
/* the added RRs, ends with the newserial SOA record. */
|
|
uint8_t* add;
|
|
/* byte length of the uncompressed wireformat RRs in add */
|
|
size_t add_len;
|
|
/* log string (if not NULL) about where data is from */
|
|
char* log_str;
|
|
/* the number of the ixfr.<num> file on disk. If 0, there is no
|
|
* file. If 1, it is file ixfr<nothingafterit>. */
|
|
int file_num;
|
|
};
|
|
|
|
/* process queries in IXFR state */
|
|
query_state_type query_ixfr(struct nsd *nsd, struct query *query);
|
|
|
|
/*
|
|
* While an IXFR is processed, in incoming IXFR that is downloaded by NSD,
|
|
* this structure keeps track of how to store the data from it. That data
|
|
* can then be used to answer IXFR queries.
|
|
*
|
|
* The structure keeps track of allocation data for the IXFR records.
|
|
* If it is cancelled, that is flagged so storage stops.
|
|
*/
|
|
struct ixfr_store {
|
|
/* the zone info, with options and zone ixfr reference */
|
|
struct zone* zone;
|
|
/* are we cancelled, it is not an IXFR, no need to store information
|
|
* any more. */
|
|
int cancelled;
|
|
/* data has been trimmed and newsoa added */
|
|
int data_trimmed;
|
|
/* the ixfr data that we are storing into */
|
|
struct ixfr_data* data;
|
|
/* capacity for the delrrs storage, size of ixfr del allocation */
|
|
size_t del_capacity;
|
|
/* capacity for the addrrs storage, size of ixfr add allocation */
|
|
size_t add_capacity;
|
|
};
|
|
|
|
/*
|
|
* Start the storage of the IXFR data from this IXFR.
|
|
* If it returns NULL, the IXFR storage stops. On malloc failure, the
|
|
* storage is returned NULL, or cancelled if failures happen later on.
|
|
*
|
|
* When done, the finish routine links the data into the memory for the zone.
|
|
* If it turns out to not be used, use the cancel routine. Or the free
|
|
* routine if the ixfr_store itself needs to be deleted too, like on error.
|
|
*
|
|
* zone: the zone structure
|
|
* ixfr_store_mem: preallocated by caller, used to allocate the store struct.
|
|
* old_serial: the start serial of the IXFR.
|
|
* new_serial: the end serial of the IXFR.
|
|
* return NULL or a fresh ixfr_store structure for adding records to the
|
|
* IXFR with this serial number. The NULL is on error.
|
|
*/
|
|
struct ixfr_store* ixfr_store_start(struct zone* zone,
|
|
struct ixfr_store* ixfr_store_mem);
|
|
|
|
/*
|
|
* Cancel the ixfr store in progress. The pointer remains valid, no store done.
|
|
* ixfr_store: this is set to cancel.
|
|
*/
|
|
void ixfr_store_cancel(struct ixfr_store* ixfr_store);
|
|
|
|
/*
|
|
* Free ixfr store structure, it is no longer used.
|
|
* ixfr_store: deleted
|
|
*/
|
|
void ixfr_store_free(struct ixfr_store* ixfr_store);
|
|
|
|
/*
|
|
* Finish ixfr store processing. Links the data into the zone ixfr data.
|
|
* ixfr_store: Data is linked into the zone struct. The ixfr_store is freed.
|
|
* nsd: nsd structure for allocation region and global options.
|
|
* log_buf: log string for the update.
|
|
*/
|
|
void ixfr_store_finish(struct ixfr_store* ixfr_store, struct nsd* nsd,
|
|
char* log_buf);
|
|
|
|
/* finish just the data activities, trim up the storage and append newsoa */
|
|
void ixfr_store_finish_data(struct ixfr_store* ixfr_store);
|
|
|
|
/*
|
|
* Add the new SOA record to the ixfr store.
|
|
* ixfr_store: stores ixfr data that is collected.
|
|
* ttl: the TTL of the SOA record
|
|
* packet: DNS packet that contains the SOA. position restored on function
|
|
* exit.
|
|
* rrlen: wire rdata length of the SOA.
|
|
*/
|
|
void ixfr_store_add_newsoa(struct ixfr_store* ixfr_store, uint32_t ttl,
|
|
struct buffer* packet, size_t rrlen);
|
|
|
|
/*
|
|
* Add the old SOA record to the ixfr store.
|
|
* ixfr_store: stores ixfr data that is collected.
|
|
* ttl: the TTL of the SOA record
|
|
* packet: DNS packet that contains the SOA. position restored on function
|
|
* exit.
|
|
* rrlen: wire rdata length of the SOA.
|
|
*/
|
|
void ixfr_store_add_oldsoa(struct ixfr_store* ixfr_store, uint32_t ttl,
|
|
struct buffer* packet, size_t rrlen);
|
|
|
|
void ixfr_store_delrr(struct ixfr_store* ixfr_store, const struct dname* dname,
|
|
uint16_t type, uint16_t klass, uint32_t ttl, struct buffer* packet,
|
|
uint16_t rrlen, struct region* temp_region);
|
|
void ixfr_store_addrr(struct ixfr_store* ixfr_store, const struct dname* dname,
|
|
uint16_t type, uint16_t klass, uint32_t ttl, struct buffer* packet,
|
|
uint16_t rrlen, struct region* temp_region);
|
|
int ixfr_store_addrr_rdatas(struct ixfr_store* ixfr_store,
|
|
const struct dname* dname, uint16_t type, uint16_t klass,
|
|
uint32_t ttl, rdata_atom_type* rdatas, ssize_t rdata_num);
|
|
int ixfr_store_delrr_uncompressed(struct ixfr_store* ixfr_store,
|
|
uint8_t* dname, size_t dname_len, uint16_t type, uint16_t klass,
|
|
uint32_t ttl, uint8_t* rdata, size_t rdata_len);
|
|
int ixfr_store_add_newsoa_rdatas(struct ixfr_store* ixfr_store,
|
|
const struct dname* dname, uint16_t type, uint16_t klass,
|
|
uint32_t ttl, rdata_atom_type* rdatas, ssize_t rdata_num);
|
|
int ixfr_store_oldsoa_uncompressed(struct ixfr_store* ixfr_store,
|
|
uint8_t* dname, size_t dname_len, uint16_t type, uint16_t klass,
|
|
uint32_t ttl, uint8_t* rdata, size_t rdata_len);
|
|
|
|
/* an AXFR has been received, the IXFRs do not connect in version number.
|
|
* Delete the unconnected IXFRs from memory */
|
|
void ixfr_store_delixfrs(struct zone* zone);
|
|
|
|
/* return if the zone has ixfr storage enabled for it */
|
|
int zone_is_ixfr_enabled(struct zone* zone);
|
|
|
|
/* create new zone_ixfr structure */
|
|
struct zone_ixfr* zone_ixfr_create(struct nsd* nsd);
|
|
|
|
/* free the zone_ixfr */
|
|
void zone_ixfr_free(struct zone_ixfr* ixfr);
|
|
|
|
/* make space to fit in the data */
|
|
void zone_ixfr_make_space(struct zone_ixfr* ixfr, struct zone* zone,
|
|
struct ixfr_data* data, struct ixfr_store* ixfr_store);
|
|
|
|
/* remove ixfr data from the zone_ixfr */
|
|
void zone_ixfr_remove(struct zone_ixfr* ixfr, struct ixfr_data* data);
|
|
|
|
/* add ixfr data to the zone_ixfr */
|
|
void zone_ixfr_add(struct zone_ixfr* ixfr, struct ixfr_data* data, int isnew);
|
|
|
|
/* find serial number in ixfr list, or NULL if not found */
|
|
struct ixfr_data* zone_ixfr_find_serial(struct zone_ixfr* ixfr,
|
|
uint32_t qserial);
|
|
|
|
/* size of the ixfr data */
|
|
size_t ixfr_data_size(struct ixfr_data* data);
|
|
|
|
/* write ixfr contents to file for the zone */
|
|
void ixfr_write_to_file(struct zone* zone, const char* zfile);
|
|
|
|
/* read ixfr contents from file for the zone */
|
|
void ixfr_read_from_file(struct nsd* nsd, struct zone* zone, const char* zfile);
|
|
|
|
/* get the current serial from the zone */
|
|
uint32_t zone_get_current_serial(struct zone* zone);
|
|
|
|
/* write the ixfr data to file */
|
|
int ixfr_write_file(struct zone* zone, struct ixfr_data* data,
|
|
const char* zfile, int file_num);
|
|
|
|
/* see if ixfr file exists */
|
|
int ixfr_file_exists(const char* zfile, int file_num);
|
|
|
|
/* rename the ixfr file */
|
|
int ixfr_rename_it(const char* zname, const char* zfile, int oldnum,
|
|
int oldtemp, int newnum, int newtemp);
|
|
|
|
/* read the file header of an ixfr file and return serial numbers. */
|
|
int ixfr_read_file_header(const char* zname, const char* zfile,
|
|
int file_num, uint32_t* oldserial, uint32_t* newserial,
|
|
size_t* data_size, int enoent_is_err);
|
|
|
|
/* unlink an ixfr file */
|
|
int ixfr_unlink_it(const char* zname, const char* zfile, int file_num,
|
|
int silent_enoent);
|
|
|
|
/* delete the ixfr files that are too many */
|
|
void ixfr_delete_superfluous_files(struct zone* zone, const char* zfile,
|
|
int dest_num_files);
|
|
|
|
#endif /* IXFR_H */
|