summaryrefslogtreecommitdiff
path: root/usr.sbin/nsd/ixfr.h
blob: eae524dc0df5dcd1267d6772780cbe7fc335a87c (plain)
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
261
262
263
264
265
266
/*
 * 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 */