1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260
|
/*
* 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 rr_type *rr);
void ixfr_store_addrr(struct ixfr_store* ixfr_store, const rr_type *rr);
int ixfr_store_addrr_rdatas(struct ixfr_store* ixfr_store, const rr_type *rr);
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 rr_type* rr);
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 */
|