summaryrefslogtreecommitdiff
path: root/src/knot/server/zones.h
blob: 33b3d7080187a3c04c3830a94b53d5e43acd2044 (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
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
/*  Copyright (C) 2011 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/*!
 * \file zones.h
 *
 * \author Lubos Slovak <lubos.slovak@nic.cz>
 *
 * Contains functions for updating zone database from configuration.
 *
 * \addtogroup server
 * @{
 */

#ifndef _KNOTD_ZONES_H_
#define _KNOTD_ZONES_H_

#include <stddef.h>

#include "common/lists.h"
#include "common/acl.h"
#include "common/evsched.h"
#include "libknot/nameserver/name-server.h"
#include "libknot/zone/zonedb.h"
#include "knot/conf/conf.h"
#include "knot/server/notify.h"
#include "knot/server/server.h"
#include "knot/server/journal.h"
#include "libknot/zone/zone.h"
#include "libknot/updates/xfr-in.h"

/* Constants. */
#define ZONES_JITTER_PCT    10 /*!< +-N% jitter to timers. */
#define IXFR_DBSYNC_TIMEOUT (60*1000) /*!< Database sync timeout = 60s. */
#define AXFR_BOOTSTRAP_RETRY (60*1000) /*!< Interval between AXFR BS retries. */

/*!
 * \brief Zone-related data.
 */
typedef struct zonedata_t
{
	/*! \brief Shortcut to zone config entry. */
	conf_zone_t *conf;

	/*! \brief Shortcut to server instance. */
	server_t  *server;

	/*! \brief Zone data lock for exclusive access. */
	pthread_mutex_t lock;
	
	/*! \brief Access control lists. */
	acl_t *xfr_out;    /*!< ACL for xfr-out.*/
	acl_t *notify_in;  /*!< ACL for notify-in.*/
	acl_t *notify_out; /*!< ACL for notify-out.*/

	/*! \brief XFR-IN scheduler. */
	struct {
		acl_t         *acl;      /*!< ACL for xfr-in.*/
		sockaddr_t     master;   /*!< Master server for xfr-in.*/
		sockaddr_t     via;      /*!< Master server transit interface.*/
		knot_key_t    tsig_key;  /*!< Master TSIG key. */
		struct event_t *timer;   /*!< Timer for REFRESH/RETRY. */
		struct event_t *expire;  /*!< Timer for REFRESH. */
		pthread_mutex_t lock;    /*!< Pending XFR/IN lock. */
		void           *wrkr;    /*!< Pending XFR/IN worker. */
		int next_id;             /*!< ID of the next awaited SOA resp.*/
		uint32_t bootstrap_retry;/*!< AXFR/IN bootstrap retry. */
		unsigned       scheduled;/*!< Scheduled operations. */ 
	} xfr_in;

	/*! \brief List of pending NOTIFY events. */
	list notify_pending;
	
	/*! \brief List of fds with pending SOA queries. */
	int soa_pending;

	/*! \brief Zone IXFR history. */
	journal_t *ixfr_db;
	struct event_t *ixfr_dbsync;   /*!< Syncing IXFR db to zonefile. */
	uint32_t zonefile_serial;
} zonedata_t;

/*!
 * \brief Update zone database according to configuration.
 *
 * Creates a new database, copies references those zones from the old database
 * which are still in the configuration, loads any new zones required and
 * replaces the database inside the namserver.
 *
 * It also creates a list of deprecated zones that should be deleted once the
 * function finishes.
 *
 * This function uses RCU mechanism to guard the access to the config and
 * nameserver and to publish the new database in the nameserver.
 *
 * \param[in] conf Configuration.
 * \param[in] ns Nameserver which holds the zone database.
 * \param[out] db_old Old database, containing only zones which should be
 *                    deleted afterwards.
 *
 * \retval KNOT_EOK
 * \retval KNOT_EINVAL
 * \retval KNOT_ERROR
 */
int zones_update_db_from_config(const conf_t *conf, knot_nameserver_t *ns,
                               knot_zonedb_t **db_old);

/*!
 * \brief Sync zone data back to text zonefile.
 *
 * In case when SOA serial of the zonefile differs from the SOA serial of the
 * loaded zone, zonefile needs to be updated.
 *
 * \note Current implementation rewrites the zone file.
 *
 * \param zone Evaluated zone.
 * \param journal Journal to sync.
 *
 * \retval KNOT_EOK if successful.
 * \retval KNOT_ERANGE if zonefile is in sync with journal.
 * \retval KNOT_EINVAL on invalid parameter.
 * \retval KNOT_ERROR on unspecified error during processing.
 */
int zones_zonefile_sync(knot_zone_t *zone, journal_t *journal);

/*!
 * \todo Document me.
 */
int zones_query_check_zone(const knot_zone_t *zone, const sockaddr_t *addr,
                           knot_key_t **tsig_key, knot_rcode_t *rcode);

/*!
 * \todo Document me.
 */
int zones_xfr_check_zone(knot_ns_xfr_t *xfr, knot_rcode_t *rcode);

/*!
 * \todo Document me.
 */
int zones_normal_query_answer(knot_nameserver_t *nameserver,
                              knot_packet_t *query, const sockaddr_t *addr,
                              uint8_t *response_wire, size_t *rsize,
                              knot_ns_transport_t transport);

/*!
 * \brief Processes normal response packet.
 *
 * \param nameserver Name server structure to provide the needed data.
 * \param from Address of the response sender.
 * \param packet Parsed response packet.
 * \param response_wire Place for the response in wire format.
 * \param rsize Input: maximum acceptable size of the response. Output: real
 *              size of the response.
 *
 * \retval KNOT_EOK if a valid response was created.
 * \retval KNOT_EINVAL on invalid parameters or packet.
 * \retval KNOT_EMALF if an error occured and the response is not valid.
 */
int zones_process_response(knot_nameserver_t *nameserver, 
                           sockaddr_t *from,
                           knot_packet_t *packet, uint8_t *response_wire,
                           size_t *rsize);

/*!
 * \brief Decides what type of transfer should be used to update the given zone.
 *.
 * \param data Zone data for associated zone.
 *
 * \retval
 */
knot_ns_xfr_type_t zones_transfer_to_use(zonedata_t *data);

int zones_save_zone(const knot_ns_xfr_t *xfr);

/*!
 * \brief Name server config hook.
 *
 * Routine for dynamic name server reconfiguration.
 *
 * \param conf Current configuration.
 * \param data Instance of the nameserver structure to update.
 *
 * \retval KNOT_EOK on success.
 * \retval KNOT_EINVAL
 * \retval KNOT_ERROR
 */
int zones_ns_conf_hook(const struct conf_t *conf, void *data);

/*!
 * \brief Store changesets in journal.
 *
 * Changesets will be stored on a permanent storage.
 * Journal may be compacted, resulting in flattening changeset history.
 *
 * \param zone Zone associated with the changeset.
 * \param src Changesets.
 *
 * \retval KNOT_EOK on success.
 * \retval KNOT_EINVAL on invalid parameters.
 * \retval KNOT_EAGAIN if journal needs to be synced with zonefile first.
 *
 * \todo Expects the xfr structure to be initialized in some way.
 * \todo Update documentation!!!
 */
int zones_store_changesets(knot_ns_xfr_t *xfr);

/*!
 * \brief Begin changesets storing transaction.
 *
 * \retval pointer to journal if successful
 * \retval NULL on failure.
 */
journal_t *zones_store_changesets_begin(knot_ns_xfr_t *xfr);

/*!
 * \brief Commit stored changesets.
 *
 * \retval KNOT_EOK on success.
 * \retval KNOT_EINVAL on invalid parameters.
 * \retval KNOT_ENOENT when no transaction is pending.
 */
int zones_store_changesets_commit(journal_t *j);

/*!
 * \brief Rollback stored changesets.
 *
 * \retval KNOT_EOK on success.
 * \retval KNOT_EINVAL on invalid parameters.
 * \retval KNOT_ENOENT when no transaction is pending.
 */
int zones_store_changesets_rollback(journal_t *j);

/*! \todo Document me. */
int zones_changesets_from_binary(knot_changesets_t *chgsets);

/*! \todo Document me. */
int zones_changesets_to_binary(knot_changesets_t *chgsets);

/*!
 * \brief Load changesets from journal.
 *
 * Changesets will be stored on a permanent storage.
 * Journal may be compacted, resulting in flattening changeset history.
 *
 * In case of KNOT_ERANGE error, whole zone content should be sent instead,
 * as the changeset history cannot be recovered.
 *
 * \param zone Zone containing a changeset journal.
 * \param dst Container to be loaded.
 * \param from Starting SOA serial (oldest).
 * \param to Ending SOA serial (newest).
 *
 * \retval KNOT_EOK on success.
 * \retval KNOT_EINVAL on invalid parameters.
 * \retval KNOT_ERANGE when changeset history cannot be reconstructed.
 *
 * \todo Expects the xfr structure to be initialized in some way.
 */
int zones_xfr_load_changesets(knot_ns_xfr_t *xfr, uint32_t serial_from,
                              uint32_t serial_to);

/*!
 * \brief Creates changesets from zones difference.
 *
 * Also saves changesets to journal, which is taken from old zone.
 *
 * \param old_zone Old zone, previously served by server.
 * \param new_zone New zone, to be served by server, after creating changesets.
 *
 * \retval KNOT_EOK on success.
 * \retval KNOT_EINVAL on invalid arguments.
 * \retval KNOT_ERANGE when new serial is lower than the old one.
 * \retval KNOT_ENODIFF when new zone's serial are equal.
 * \retval KNOT_ERROR when there was error creating changesets.
 */
int zones_create_and_save_changesets(const knot_zone_t *old_zone,
                                     const knot_zone_t *new_zone);

/*!
 * \brief Update zone timers.
 *
 * REFRESH/RETRY/EXPIRE timers are updated according to SOA.
 *
 * \param sched Event scheduler.
 * \param zone Related zone.
 * \param cfzone Related zone contents. If NULL, configuration is
 *               reused.
 *
 * \retval KNOT_EOK
 * \retval KNOT_EINVAL
 * \retval KNOT_ERROR
 */
int zones_timers_update(knot_zone_t *zone, conf_zone_t *cfzone, evsched_t *sch);

/*!
 * \brief Cancel pending NOTIFY timer.
 *
 * \warning Expects locked zonedata lock.
 *
 * \param zd Zone data.
 * \param ev NOTIFY event.
 *
 * \retval KNOT_EOK
 * \retval KNOT_ERROR
 * \retval KNOT_EINVAL
 */
int zones_cancel_notify(zonedata_t *zd, notify_ev_t *ev);

#endif // _KNOTD_ZONES_H_

/*! @} */