xref: /dragonfly/contrib/ldns/rr_functions.c (revision 7733acb50455a11cc2ee36edd926ff0fa3361e9a)
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  */
30 static ldns_rdf *
ldns_rr_function(ldns_rr_type type,const ldns_rr * rr,size_t pos)31 ldns_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  */
47 static bool
ldns_rr_set_function(ldns_rr_type type,ldns_rr * rr,ldns_rdf * rdf,size_t pos)48 ldns_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 */
60 ldns_rdf *
ldns_rr_a_address(const ldns_rr * r)61 ldns_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 
71 bool
ldns_rr_a_set_address(ldns_rr * r,ldns_rdf * f)72 ldns_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 */
90 ldns_rdf *
ldns_rr_ns_nsdname(const ldns_rr * r)91 ldns_rr_ns_nsdname(const ldns_rr *r)
92 {
93           return ldns_rr_function(LDNS_RR_TYPE_NS, r, 0);
94 }
95 
96 /* MX record */
97 ldns_rdf *
ldns_rr_mx_preference(const ldns_rr * r)98 ldns_rr_mx_preference(const ldns_rr *r)
99 {
100           return ldns_rr_function(LDNS_RR_TYPE_MX, r, 0);
101 }
102 
103 ldns_rdf *
ldns_rr_mx_exchange(const ldns_rr * r)104 ldns_rr_mx_exchange(const ldns_rr *r)
105 {
106           return ldns_rr_function(LDNS_RR_TYPE_MX, r, 1);
107 }
108 
109 /* RRSIG record */
110 ldns_rdf *
ldns_rr_rrsig_typecovered(const ldns_rr * r)111 ldns_rr_rrsig_typecovered(const ldns_rr *r)
112 {
113           return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 0);
114 }
115 
116 bool
ldns_rr_rrsig_set_typecovered(ldns_rr * r,ldns_rdf * f)117 ldns_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 
122 ldns_rdf *
ldns_rr_rrsig_algorithm(const ldns_rr * r)123 ldns_rr_rrsig_algorithm(const ldns_rr *r)
124 {
125           return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 1);
126 }
127 
128 bool
ldns_rr_rrsig_set_algorithm(ldns_rr * r,ldns_rdf * f)129 ldns_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 
134 ldns_rdf *
ldns_rr_rrsig_labels(const ldns_rr * r)135 ldns_rr_rrsig_labels(const ldns_rr *r)
136 {
137           return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 2);
138 }
139 
140 bool
ldns_rr_rrsig_set_labels(ldns_rr * r,ldns_rdf * f)141 ldns_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 
146 ldns_rdf *
ldns_rr_rrsig_origttl(const ldns_rr * r)147 ldns_rr_rrsig_origttl(const ldns_rr *r)
148 {
149           return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 3);
150 }
151 
152 bool
ldns_rr_rrsig_set_origttl(ldns_rr * r,ldns_rdf * f)153 ldns_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 
158 ldns_rdf *
ldns_rr_rrsig_expiration(const ldns_rr * r)159 ldns_rr_rrsig_expiration(const ldns_rr *r)
160 {
161           return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 4);
162 }
163 
164 bool
ldns_rr_rrsig_set_expiration(ldns_rr * r,ldns_rdf * f)165 ldns_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 
170 ldns_rdf *
ldns_rr_rrsig_inception(const ldns_rr * r)171 ldns_rr_rrsig_inception(const ldns_rr *r)
172 {
173           return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 5);
174 }
175 
176 bool
ldns_rr_rrsig_set_inception(ldns_rr * r,ldns_rdf * f)177 ldns_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 
182 ldns_rdf *
ldns_rr_rrsig_keytag(const ldns_rr * r)183 ldns_rr_rrsig_keytag(const ldns_rr *r)
184 {
185           return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 6);
186 }
187 
188 bool
ldns_rr_rrsig_set_keytag(ldns_rr * r,ldns_rdf * f)189 ldns_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 
194 ldns_rdf *
ldns_rr_rrsig_signame(const ldns_rr * r)195 ldns_rr_rrsig_signame(const ldns_rr *r)
196 {
197           return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 7);
198 }
199 
200 bool
ldns_rr_rrsig_set_signame(ldns_rr * r,ldns_rdf * f)201 ldns_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 
206 ldns_rdf *
ldns_rr_rrsig_sig(const ldns_rr * r)207 ldns_rr_rrsig_sig(const ldns_rr *r)
208 {
209           return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 8);
210 }
211 
212 bool
ldns_rr_rrsig_set_sig(ldns_rr * r,ldns_rdf * f)213 ldns_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 */
219 ldns_rdf *
ldns_rr_dnskey_flags(const ldns_rr * r)220 ldns_rr_dnskey_flags(const ldns_rr *r)
221 {
222           return ldns_rr_function(LDNS_RR_TYPE_DNSKEY, r, 0);
223 }
224 
225 bool
ldns_rr_dnskey_set_flags(ldns_rr * r,ldns_rdf * f)226 ldns_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 
231 ldns_rdf *
ldns_rr_dnskey_protocol(const ldns_rr * r)232 ldns_rr_dnskey_protocol(const ldns_rr *r)
233 {
234           return ldns_rr_function(LDNS_RR_TYPE_DNSKEY, r, 1);
235 }
236 
237 bool
ldns_rr_dnskey_set_protocol(ldns_rr * r,ldns_rdf * f)238 ldns_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 
243 ldns_rdf *
ldns_rr_dnskey_algorithm(const ldns_rr * r)244 ldns_rr_dnskey_algorithm(const ldns_rr *r)
245 {
246           return ldns_rr_function(LDNS_RR_TYPE_DNSKEY, r, 2);
247 }
248 
249 bool
ldns_rr_dnskey_set_algorithm(ldns_rr * r,ldns_rdf * f)250 ldns_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 
255 ldns_rdf *
ldns_rr_dnskey_key(const ldns_rr * r)256 ldns_rr_dnskey_key(const ldns_rr *r)
257 {
258           return ldns_rr_function(LDNS_RR_TYPE_DNSKEY, r, 3);
259 }
260 
261 bool
ldns_rr_dnskey_set_key(ldns_rr * r,ldns_rdf * f)262 ldns_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 
267 size_t
ldns_rr_dnskey_key_size_raw(const unsigned char * keydata,const size_t len,const ldns_algorithm alg)268 ldns_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 
343 size_t
ldns_rr_dnskey_key_size(const ldns_rr * key)344 ldns_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 
ldns_soa_serial_identity(uint32_t ATTR_UNUSED (unused),void * data)356 uint32_t ldns_soa_serial_identity(uint32_t ATTR_UNUSED(unused), void *data)
357 {
358           return (uint32_t) (intptr_t) data;
359 }
360 
ldns_soa_serial_increment(uint32_t s,void * ATTR_UNUSED (unused))361 uint32_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 
ldns_soa_serial_increment_by(uint32_t s,void * data)366 uint32_t ldns_soa_serial_increment_by(uint32_t s, void *data)
367 {
368           return s + (intptr_t) data;
369 }
370 
ldns_soa_serial_datecounter(uint32_t s,void * data)371 uint32_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 
ldns_soa_serial_unixtime(uint32_t s,void * data)383 uint32_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 
390 void
ldns_rr_soa_increment(ldns_rr * soa)391 ldns_rr_soa_increment(ldns_rr *soa)
392 {
393           ldns_rr_soa_increment_func_data(soa, ldns_soa_serial_increment, NULL);
394 }
395 
396 void
ldns_rr_soa_increment_func(ldns_rr * soa,ldns_soa_serial_increment_func_t f)397 ldns_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 
402 void
ldns_rr_soa_increment_func_data(ldns_rr * soa,ldns_soa_serial_increment_func_t f,void * data)403 ldns_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 
425 void
ldns_rr_soa_increment_func_int(ldns_rr * soa,ldns_soa_serial_increment_func_t f,int data)426 ldns_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