1/*
2 * rr_function.c
3 *
4 * function that operate on specific rr types
5 *
6 * (c) NLnet Labs, 2004-2006
7 * See the file LICENSE for the license
8 */
9
10/*
11 * These come strait from perldoc Net::DNS::RR::xxx
12 * first the read variant, then the write. This is
13 * not complete.
14 */
15
16#include <ldns/config.h>
17
18#include <ldns/ldns.h>
19
20#include <limits.h>
21#include <strings.h>
22
23/**
24 * return a specific rdf
25 * \param[in] type type of RR
26 * \param[in] rr   the rr itself
27 * \param[in] pos  at which position to get it
28 * \return the rdf sought
29 */
30static ldns_rdf *
31ldns_rr_function(ldns_rr_type type, const ldns_rr *rr, size_t pos)
32{
33        if (!rr || ldns_rr_get_type(rr) != type) {
34                return NULL;
35        }
36        return ldns_rr_rdf(rr, pos);
37}
38
39/**
40 * set a specific rdf
41 * \param[in] type type of RR
42 * \param[in] rr   the rr itself
43 * \param[in] rdf  the rdf to set
44 * \param[in] pos  at which position to set it
45 * \return true or false
46 */
47static bool
48ldns_rr_set_function(ldns_rr_type type, ldns_rr *rr, ldns_rdf *rdf, size_t pos)
49{
50        ldns_rdf *pop;
51        if (!rr || ldns_rr_get_type(rr) != type) {
52                return false;
53        }
54        pop = ldns_rr_set_rdf(rr, rdf, pos);
55 	ldns_rdf_deep_free(pop);
56        return true;
57}
58
59/* A/AAAA records */
60ldns_rdf *
61ldns_rr_a_address(const ldns_rr *r)
62{
63	/* 2 types to check, cannot use the macro */
64	if (!r || (ldns_rr_get_type(r) != LDNS_RR_TYPE_A &&
65			ldns_rr_get_type(r) != LDNS_RR_TYPE_AAAA)) {
66		return NULL;
67	}
68	return ldns_rr_rdf(r, 0);
69}
70
71bool
72ldns_rr_a_set_address(ldns_rr *r, ldns_rdf *f)
73{
74	/* 2 types to check, cannot use the macro... */
75	ldns_rdf *pop;
76	if (!r || (ldns_rr_get_type(r) != LDNS_RR_TYPE_A &&
77			ldns_rr_get_type(r) != LDNS_RR_TYPE_AAAA)) {
78		return false;
79	}
80	pop = ldns_rr_set_rdf(r, f, 0);
81	if (pop) {
82		LDNS_FREE(pop);
83		return true;
84	} else {
85		return false;
86	}
87}
88
89/* NS record */
90ldns_rdf *
91ldns_rr_ns_nsdname(const ldns_rr *r)
92{
93	return ldns_rr_function(LDNS_RR_TYPE_NS, r, 0);
94}
95
96/* MX record */
97ldns_rdf *
98ldns_rr_mx_preference(const ldns_rr *r)
99{
100	return ldns_rr_function(LDNS_RR_TYPE_MX, r, 0);
101}
102
103ldns_rdf *
104ldns_rr_mx_exchange(const ldns_rr *r)
105{
106	return ldns_rr_function(LDNS_RR_TYPE_MX, r, 1);
107}
108
109/* RRSIG record */
110ldns_rdf *
111ldns_rr_rrsig_typecovered(const ldns_rr *r)
112{
113	return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 0);
114}
115
116bool
117ldns_rr_rrsig_set_typecovered(ldns_rr *r, ldns_rdf *f)
118{
119	return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 0);
120}
121
122ldns_rdf *
123ldns_rr_rrsig_algorithm(const ldns_rr *r)
124{
125	return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 1);
126}
127
128bool
129ldns_rr_rrsig_set_algorithm(ldns_rr *r, ldns_rdf *f)
130{
131	return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 1);
132}
133
134ldns_rdf *
135ldns_rr_rrsig_labels(const ldns_rr *r)
136{
137	return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 2);
138}
139
140bool
141ldns_rr_rrsig_set_labels(ldns_rr *r, ldns_rdf *f)
142{
143	return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 2);
144}
145
146ldns_rdf *
147ldns_rr_rrsig_origttl(const ldns_rr *r)
148{
149	return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 3);
150}
151
152bool
153ldns_rr_rrsig_set_origttl(ldns_rr *r, ldns_rdf *f)
154{
155	return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 3);
156}
157
158ldns_rdf *
159ldns_rr_rrsig_expiration(const ldns_rr *r)
160{
161	return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 4);
162}
163
164bool
165ldns_rr_rrsig_set_expiration(ldns_rr *r, ldns_rdf *f)
166{
167	return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 4);
168}
169
170ldns_rdf *
171ldns_rr_rrsig_inception(const ldns_rr *r)
172{
173	return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 5);
174}
175
176bool
177ldns_rr_rrsig_set_inception(ldns_rr *r, ldns_rdf *f)
178{
179	return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 5);
180}
181
182ldns_rdf *
183ldns_rr_rrsig_keytag(const ldns_rr *r)
184{
185	return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 6);
186}
187
188bool
189ldns_rr_rrsig_set_keytag(ldns_rr *r, ldns_rdf *f)
190{
191	return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 6);
192}
193
194ldns_rdf *
195ldns_rr_rrsig_signame(const ldns_rr *r)
196{
197	return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 7);
198}
199
200bool
201ldns_rr_rrsig_set_signame(ldns_rr *r, ldns_rdf *f)
202{
203	return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 7);
204}
205
206ldns_rdf *
207ldns_rr_rrsig_sig(const ldns_rr *r)
208{
209	return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 8);
210}
211
212bool
213ldns_rr_rrsig_set_sig(ldns_rr *r, ldns_rdf *f)
214{
215	return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 8);
216}
217
218/* DNSKEY record */
219ldns_rdf *
220ldns_rr_dnskey_flags(const ldns_rr *r)
221{
222	return ldns_rr_function(LDNS_RR_TYPE_DNSKEY, r, 0);
223}
224
225bool
226ldns_rr_dnskey_set_flags(ldns_rr *r, ldns_rdf *f)
227{
228	return ldns_rr_set_function(LDNS_RR_TYPE_DNSKEY, r, f, 0);
229}
230
231ldns_rdf *
232ldns_rr_dnskey_protocol(const ldns_rr *r)
233{
234	return ldns_rr_function(LDNS_RR_TYPE_DNSKEY, r, 1);
235}
236
237bool
238ldns_rr_dnskey_set_protocol(ldns_rr *r, ldns_rdf *f)
239{
240	return ldns_rr_set_function(LDNS_RR_TYPE_DNSKEY, r, f, 1);
241}
242
243ldns_rdf *
244ldns_rr_dnskey_algorithm(const ldns_rr *r)
245{
246	return ldns_rr_function(LDNS_RR_TYPE_DNSKEY, r, 2);
247}
248
249bool
250ldns_rr_dnskey_set_algorithm(ldns_rr *r, ldns_rdf *f)
251{
252	return ldns_rr_set_function(LDNS_RR_TYPE_DNSKEY, r, f, 2);
253}
254
255ldns_rdf *
256ldns_rr_dnskey_key(const ldns_rr *r)
257{
258	return ldns_rr_function(LDNS_RR_TYPE_DNSKEY, r, 3);
259}
260
261bool
262ldns_rr_dnskey_set_key(ldns_rr *r, ldns_rdf *f)
263{
264	return ldns_rr_set_function(LDNS_RR_TYPE_DNSKEY, r, f, 3);
265}
266
267size_t
268ldns_rr_dnskey_key_size_raw(const unsigned char* keydata,
269                            const size_t len,
270                            const ldns_algorithm alg)
271{
272#ifdef USE_DSA
273	/* for DSA keys */
274	uint8_t t;
275#endif /* USE_DSA */
276
277	/* for RSA keys */
278	uint16_t exp;
279	uint16_t int16;
280
281	switch ((ldns_signing_algorithm)alg) {
282#ifdef USE_DSA
283	case LDNS_SIGN_DSA:
284	case LDNS_SIGN_DSA_NSEC3:
285		if (len > 0) {
286			t = keydata[0];
287			return (64 + t*8)*8;
288		} else {
289			return 0;
290		}
291		break;
292#endif /* USE_DSA */
293	case LDNS_SIGN_RSAMD5:
294	case LDNS_SIGN_RSASHA1:
295	case LDNS_SIGN_RSASHA1_NSEC3:
296#ifdef USE_SHA2
297	case LDNS_SIGN_RSASHA256:
298	case LDNS_SIGN_RSASHA512:
299#endif
300		if (len > 0) {
301			if (keydata[0] == 0) {
302				/* big exponent */
303				if (len > 3) {
304					memmove(&int16, keydata + 1, 2);
305					exp = ntohs(int16);
306					return (len - exp - 3)*8;
307				} else {
308					return 0;
309				}
310			} else {
311				exp = keydata[0];
312				return (len-exp-1)*8;
313			}
314		} else {
315			return 0;
316		}
317		break;
318#ifdef USE_GOST
319	case LDNS_SIGN_ECC_GOST:
320		return 512;
321#endif
322#ifdef USE_ECDSA
323        case LDNS_SIGN_ECDSAP256SHA256:
324                return 256;
325        case LDNS_SIGN_ECDSAP384SHA384:
326                return 384;
327#endif
328#ifdef USE_ED25519
329	case LDNS_SIGN_ED25519:
330		return 256;
331#endif
332#ifdef USE_ED448
333	case LDNS_SIGN_ED448:
334		return 456;
335#endif
336	case LDNS_SIGN_HMACMD5:
337		return len;
338	default:
339		return 0;
340	}
341}
342
343size_t
344ldns_rr_dnskey_key_size(const ldns_rr *key)
345{
346	if (!key || !ldns_rr_dnskey_key(key)
347			|| !ldns_rr_dnskey_algorithm(key)) {
348		return 0;
349	}
350	return ldns_rr_dnskey_key_size_raw((unsigned char*)ldns_rdf_data(ldns_rr_dnskey_key(key)),
351	                                   ldns_rdf_size(ldns_rr_dnskey_key(key)),
352	                                   ldns_rdf2native_int8(ldns_rr_dnskey_algorithm(key))
353	                                  );
354}
355
356uint32_t ldns_soa_serial_identity(uint32_t ATTR_UNUSED(unused), void *data)
357{
358	return (uint32_t) (intptr_t) data;
359}
360
361uint32_t ldns_soa_serial_increment(uint32_t s, void *ATTR_UNUSED(unused))
362{
363	return ldns_soa_serial_increment_by(s, (void *)1);
364}
365
366uint32_t ldns_soa_serial_increment_by(uint32_t s, void *data)
367{
368	return s + (intptr_t) data;
369}
370
371uint32_t ldns_soa_serial_datecounter(uint32_t s, void *data)
372{
373	struct tm tm;
374	char s_str[11];
375	int32_t new_s;
376	time_t t = data ? (time_t) (intptr_t) data : ldns_time(NULL);
377
378	(void) strftime(s_str, 11, "%Y%m%d00", localtime_r(&t, &tm));
379	new_s = (int32_t) atoi(s_str);
380	return new_s - ((int32_t) s) <= 0 ? s+1 : ((uint32_t) new_s);
381}
382
383uint32_t ldns_soa_serial_unixtime(uint32_t s, void *data)
384{
385	int32_t new_s = data ? (int32_t) (intptr_t) data
386			     : (int32_t) ldns_time(NULL);
387	return new_s - ((int32_t) s) <= 0 ? s+1 : ((uint32_t) new_s);
388}
389
390void
391ldns_rr_soa_increment(ldns_rr *soa)
392{
393	ldns_rr_soa_increment_func_data(soa, ldns_soa_serial_increment, NULL);
394}
395
396void
397ldns_rr_soa_increment_func(ldns_rr *soa, ldns_soa_serial_increment_func_t f)
398{
399	ldns_rr_soa_increment_func_data(soa, f, NULL);
400}
401
402void
403ldns_rr_soa_increment_func_data(ldns_rr *soa,
404		ldns_soa_serial_increment_func_t f, void *data)
405{
406	ldns_rdf *prev_soa_serial_rdf;
407	if ( !soa || !f || ldns_rr_get_type(soa) != LDNS_RR_TYPE_SOA
408			|| !ldns_rr_rdf(soa, 2)) {
409		return;
410	}
411	prev_soa_serial_rdf = ldns_rr_set_rdf(
412		  soa
413		, ldns_native2rdf_int32(
414			  LDNS_RDF_TYPE_INT32
415			, (*f)( ldns_rdf2native_int32(
416					ldns_rr_rdf(soa, 2))
417			      , data
418			)
419		)
420		, 2
421	);
422	LDNS_FREE(prev_soa_serial_rdf);
423}
424
425void
426ldns_rr_soa_increment_func_int(ldns_rr *soa,
427		ldns_soa_serial_increment_func_t f, int data)
428{
429	ldns_rr_soa_increment_func_data(soa, f, (void *) (intptr_t) data);
430}
431
432