1 /*------------------------------------------------------------------------------
2 *
3 * Copyright (c) 2011-2021, EURid vzw. All rights reserved.
4 * The YADIFA TM software product is provided under the BSD 3-clause license:
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * * Neither the name of EURid nor the names of its contributors may be
16 * used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 *------------------------------------------------------------------------------
32 *
33 */
34
35 /** @defgroup dnsdbupdate Dynamic update functions
36 * @ingroup dnsdb
37 * @brief
38 *
39 * @{
40 */
41 /*------------------------------------------------------------------------------
42 *
43 * USE INCLUDES */
44 #include "dnsdb/dnsdb-config.h"
45 #include <stdio.h>
46 #include <stdlib.h>
47
48 #include "dnsdb/dynupdate-message.h"
49
50 #define DMSGPCKT_TAG 0x544b435047534d44
51
52 // Disable detailled diff log even in debug builds
53
54 #define DYNUPDATE_DIFF_DETAILLED_LOG 0
55
56 #ifndef DYNUPDATE_DIFF_DETAILLED_LOG
57 #if DEBUG
58 #define DYNUPDATE_DIFF_DETAILLED_LOG 1
59 #else
60 #define DYNUPDATE_DIFF_DETAILLED_LOG 0
61 #endif
62 #endif
63
64 ///////////////////////////////////////////////////////////////////////////////
65
66 /**
67 * Initialises a simple update buffer
68 *
69 * @param dmsg
70 */
71
72 void
dynupdate_message_init(dynupdate_message * dmsg,const u8 * origin,u16 rclass)73 dynupdate_message_init(dynupdate_message *dmsg, const u8 *origin, u16 rclass)
74 {
75 dmsg->size = MAX_U16;
76 MALLOC_OR_DIE(u8*, dmsg->packet, dmsg->size, DMSGPCKT_TAG);
77 // packet_writer_init is for valid messages. For writing a new message use:
78 packet_writer_create(&dmsg->pw, dmsg->packet, dmsg->size);
79 dmsg->rclass = rclass;
80 message_header *hdr = (message_header*)dmsg->packet;
81 #if DEBUG
82 memset(dmsg->packet, 0xcc, dmsg->size);
83 #endif
84 ZEROMEMORY(hdr, DNS_HEADER_LENGTH);
85 hdr->opcode = OPCODE_UPDATE;
86 packet_writer_add_fqdn(&dmsg->pw, origin);
87 packet_writer_add_u16(&dmsg->pw, TYPE_SOA);
88 packet_writer_add_u16(&dmsg->pw, rclass);
89 hdr->qdcount = NU16(1);
90 }
91
92 void
dynupdate_message_reset(dynupdate_message * dmsg,const u8 * origin,u16 rclass)93 dynupdate_message_reset(dynupdate_message *dmsg, const u8 *origin, u16 rclass)
94 {
95 // packet_writer_init is for valid messages. For writing a new message use:
96 packet_writer_create(&dmsg->pw, dmsg->packet, dmsg->size);
97 dmsg->rclass = rclass;
98 message_header *hdr = (message_header*)dmsg->packet;
99 #if DEBUG
100 memset(dmsg->packet, 0xcc, dmsg->size);
101 #endif
102 ZEROMEMORY(hdr, DNS_HEADER_LENGTH);
103 hdr->opcode = OPCODE_UPDATE;
104 packet_writer_add_fqdn(&dmsg->pw, origin);
105 packet_writer_add_u16(&dmsg->pw, TYPE_SOA);
106 packet_writer_add_u16(&dmsg->pw, rclass);
107 hdr->qdcount = NU16(1);
108 }
109
110 /**
111 * Releases resources.
112 *
113 * @param dmsg
114 */
115
116 void
dynupdate_message_finalize(dynupdate_message * dmsg)117 dynupdate_message_finalize(dynupdate_message *dmsg)
118 {
119 //packet_writer_finalize(&dmsg->pw);
120 free(dmsg->packet);
121 }
122
123 /**
124 * Sets a reader up for the buffer.
125 *
126 * @param dmsg
127 * @param purd
128 */
129
130 void
dynupdate_message_set_reader(dynupdate_message * dmsg,packet_unpack_reader_data * purd)131 dynupdate_message_set_reader(dynupdate_message *dmsg, packet_unpack_reader_data *purd)
132 {
133 yassert(dmsg->pw.packet_offset >= DNS_HEADER_LENGTH);
134
135 packet_reader_init(purd, dmsg->packet, dmsg->pw.packet_offset);
136 }
137
138 /**
139 * Return the number of update records.
140 *
141 * @param dmsg
142 * @return
143 */
144
145 u16
dynupdate_message_get_count(dynupdate_message * dmsg)146 dynupdate_message_get_count(dynupdate_message *dmsg)
147 {
148 message_header *hdr = (message_header*)dmsg->packet;
149 u16 count = ntohs(hdr->nscount);
150 return count;
151 }
152
153 /**
154 * Adds a dnskey record to the buffer
155 *
156 * @param dmsg
157 * @param ttl
158 * @param key
159 * @return
160 */
161
162 ya_result
dynupdate_message_add_dnskey(dynupdate_message * dmsg,s32 ttl,const dnssec_key * key)163 dynupdate_message_add_dnskey(dynupdate_message *dmsg, s32 ttl, const dnssec_key *key)
164 {
165 u32 rdata_size = key->vtbl->dnssec_key_rdatasize(key);
166 u32 remaining = packet_writer_get_remaining_capacity(&dmsg->pw);
167
168 ya_result ret = BUFFER_WOULD_OVERFLOW;
169
170 // the first 2 is assuming compression will take place
171 // which is as it should be since the messages are initialised with the fqdn of the zone
172
173 if(remaining >= 2 + 2 + 2 + 4 + 2 + rdata_size)
174 {
175 if(ISOK(ret = packet_writer_add_fqdn(&dmsg->pw, &dmsg->packet[DNS_HEADER_LENGTH])))
176 {
177 packet_writer_add_u16(&dmsg->pw, TYPE_DNSKEY);
178 packet_writer_add_u16(&dmsg->pw, dmsg->rclass);
179 packet_writer_add_u32(&dmsg->pw, htonl(ttl));
180 packet_writer_add_u16(&dmsg->pw, htons(rdata_size));
181 key->vtbl->dnssec_key_writerdata(key, packet_writer_get_next_u8_ptr(&dmsg->pw), rdata_size);
182 packet_writer_forward(&dmsg->pw, rdata_size);
183 message_header *hdr = (message_header*)dmsg->packet;
184 hdr->nscount = htons(ntohs(hdr->nscount) + 1);
185 }
186 }
187
188 return ret;
189 }
190
191 /**
192 * Deletes a dnskey record to the buffer
193 *
194 * @param dmsg
195 * @param ttl
196 * @param key
197 * @return
198 */
199
200 ya_result
dynupdate_message_del_dnskey(dynupdate_message * dmsg,const dnssec_key * key)201 dynupdate_message_del_dnskey(dynupdate_message *dmsg, const dnssec_key *key)
202 {
203 u32 rdata_size = key->vtbl->dnssec_key_rdatasize(key);
204 u32 remaining = packet_writer_get_remaining_capacity(&dmsg->pw);
205
206 ya_result ret = BUFFER_WOULD_OVERFLOW;
207
208 if(remaining >= 2 + 2 + 2 + 4 + 2 + rdata_size)
209 {
210 if(ISOK(ret = packet_writer_add_fqdn(&dmsg->pw, &dmsg->packet[DNS_HEADER_LENGTH])))
211 {
212 packet_writer_add_u16(&dmsg->pw, TYPE_DNSKEY);
213 packet_writer_add_u16(&dmsg->pw, CLASS_NONE);
214 packet_writer_add_u32(&dmsg->pw, 0);
215 packet_writer_add_u16(&dmsg->pw, htons(rdata_size));
216 key->vtbl->dnssec_key_writerdata(key, packet_writer_get_next_u8_ptr(&dmsg->pw), rdata_size);
217 packet_writer_forward(&dmsg->pw, rdata_size);
218 message_header *hdr = (message_header*)dmsg->packet;
219 hdr->nscount = htons(ntohs(hdr->nscount) + 1);
220 }
221 }
222
223 return ret;
224 }
225
226 /**
227 * Appends a "add RR" command to the buffer.
228 *
229 * @param dmsg
230 * @param fqdn
231 * @param rtype
232 * @param ttl
233 * @param rdata_size
234 * @param rdata
235 * @return
236 */
237
238 ya_result
dynupdate_message_add_record(dynupdate_message * dmsg,const u8 * fqdn,u16 rtype,s32 ttl,u16 rdata_size,void * rdata)239 dynupdate_message_add_record(dynupdate_message *dmsg, const u8 *fqdn, u16 rtype, s32 ttl, u16 rdata_size, void *rdata)
240 {
241 ya_result ret;
242 if(ISOK(ret = packet_writer_add_record(&dmsg->pw, fqdn, rtype, dmsg->rclass, ttl, rdata, rdata_size)))
243 {
244 message_header *hdr = (message_header*)dmsg->packet;
245 hdr->nscount = htons(ntohs(hdr->nscount) + 1);
246 }
247 return ret;
248 }
249
250 /**
251 * Appends a "delete RR" command to the buffer.
252 *
253 * @param dmsg
254 * @param fqdn
255 * @param rtype
256 * @param ttl
257 * @param rdata_size
258 * @param rdata
259 * @return
260 */
261
262 ya_result
dynupdate_message_del_record(dynupdate_message * dmsg,const u8 * fqdn,u16 rtype,s32 ttl,u16 rdata_size,void * rdata)263 dynupdate_message_del_record(dynupdate_message *dmsg, const u8 *fqdn, u16 rtype, s32 ttl, u16 rdata_size, void *rdata)
264 {
265 ya_result ret;
266 if(ISOK(ret = packet_writer_add_record(&dmsg->pw, fqdn, rtype, TYPE_NONE, ttl, rdata, rdata_size)))
267 {
268 message_header *hdr = (message_header*)dmsg->packet;
269 hdr->nscount = htons(ntohs(hdr->nscount) + 1);
270 }
271 return ret;
272 }
273
274 /**
275 *
276 * Appends a "delete RRSET" command to the buffer.
277 *
278 * @param dmsg
279 * @param fqdn
280 * @param rtype
281 * @return
282 */
283
284 ya_result
dynupdate_message_del_record_set(dynupdate_message * dmsg,const u8 * fqdn,u16 rtype)285 dynupdate_message_del_record_set(dynupdate_message *dmsg, const u8 *fqdn, u16 rtype)
286 {
287 ya_result ret;
288 if(ISOK(ret = packet_writer_add_record(&dmsg->pw, fqdn, rtype, TYPE_ANY, 0, NULL, 0)))
289 {
290 message_header *hdr = (message_header*)dmsg->packet;
291 hdr->nscount = htons(ntohs(hdr->nscount) + 1);
292 }
293 return ret;
294 }
295
296 /**
297 * Appends a "delete fqdn" command to the buffer.
298 *
299 * @param dmsg
300 * @param fqdn
301 * @return
302 */
303
304 ya_result
dynupdate_message_del_fqdn(dynupdate_message * dmsg,const u8 * fqdn)305 dynupdate_message_del_fqdn(dynupdate_message *dmsg, const u8 *fqdn)
306 {
307 ya_result ret;
308 if(ISOK(ret = packet_writer_add_record(&dmsg->pw, fqdn, TYPE_ANY, TYPE_ANY, 0, NULL, 0)))
309 {
310 message_header *hdr = (message_header*)dmsg->packet;
311 hdr->nscount = htons(ntohs(hdr->nscount) + 1);
312 }
313 return ret;
314 }
315
316