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 postion 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 postion 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 /* for DSA keys */ 273 uint8_t t; 274 275 /* for RSA keys */ 276 uint16_t exp; 277 uint16_t int16; 278 279 switch ((ldns_signing_algorithm)alg) { 280 case LDNS_SIGN_DSA: 281 case LDNS_SIGN_DSA_NSEC3: 282 if (len > 0) { 283 t = keydata[0]; 284 return (64 + t*8)*8; 285 } else { 286 return 0; 287 } 288 break; 289 case LDNS_SIGN_RSAMD5: 290 case LDNS_SIGN_RSASHA1: 291 case LDNS_SIGN_RSASHA1_NSEC3: 292#ifdef USE_SHA2 293 case LDNS_SIGN_RSASHA256: 294 case LDNS_SIGN_RSASHA512: 295#endif 296 if (len > 0) { 297 if (keydata[0] == 0) { 298 /* big exponent */ 299 if (len > 3) { 300 memmove(&int16, keydata + 1, 2); 301 exp = ntohs(int16); 302 return (len - exp - 3)*8; 303 } else { 304 return 0; 305 } 306 } else { 307 exp = keydata[0]; 308 return (len-exp-1)*8; 309 } 310 } else { 311 return 0; 312 } 313 break; 314#ifdef USE_GOST 315 case LDNS_SIGN_ECC_GOST: 316 return 512; 317#endif 318#ifdef USE_ECDSA 319 case LDNS_SIGN_ECDSAP256SHA256: 320 return 256; 321 case LDNS_SIGN_ECDSAP384SHA384: 322 return 384; 323#endif 324#ifdef USE_ED25519 325 case LDNS_SIGN_ED25519: 326 return 256; 327#endif 328#ifdef USE_ED448 329 case LDNS_SIGN_ED448: 330 return 456; 331#endif 332 case LDNS_SIGN_HMACMD5: 333 return len; 334 default: 335 return 0; 336 } 337} 338 339size_t 340ldns_rr_dnskey_key_size(const ldns_rr *key) 341{ 342 if (!key || !ldns_rr_dnskey_key(key) 343 || !ldns_rr_dnskey_algorithm(key)) { 344 return 0; 345 } 346 return ldns_rr_dnskey_key_size_raw((unsigned char*)ldns_rdf_data(ldns_rr_dnskey_key(key)), 347 ldns_rdf_size(ldns_rr_dnskey_key(key)), 348 ldns_rdf2native_int8(ldns_rr_dnskey_algorithm(key)) 349 ); 350} 351 352uint32_t ldns_soa_serial_identity(uint32_t ATTR_UNUSED(unused), void *data) 353{ 354 return (uint32_t) (intptr_t) data; 355} 356 357uint32_t ldns_soa_serial_increment(uint32_t s, void *ATTR_UNUSED(unused)) 358{ 359 return ldns_soa_serial_increment_by(s, (void *)1); 360} 361 362uint32_t ldns_soa_serial_increment_by(uint32_t s, void *data) 363{ 364 return s + (intptr_t) data; 365} 366 367uint32_t ldns_soa_serial_datecounter(uint32_t s, void *data) 368{ 369 struct tm tm; 370 char s_str[11]; 371 int32_t new_s; 372 time_t t = data ? (time_t) (intptr_t) data : ldns_time(NULL); 373 374 (void) strftime(s_str, 11, "%Y%m%d00", localtime_r(&t, &tm)); 375 new_s = (int32_t) atoi(s_str); 376 return new_s - ((int32_t) s) <= 0 ? s+1 : ((uint32_t) new_s); 377} 378 379uint32_t ldns_soa_serial_unixtime(uint32_t s, void *data) 380{ 381 int32_t new_s = data ? (int32_t) (intptr_t) data 382 : (int32_t) ldns_time(NULL); 383 return new_s - ((int32_t) s) <= 0 ? s+1 : ((uint32_t) new_s); 384} 385 386void 387ldns_rr_soa_increment(ldns_rr *soa) 388{ 389 ldns_rr_soa_increment_func_data(soa, ldns_soa_serial_increment, NULL); 390} 391 392void 393ldns_rr_soa_increment_func(ldns_rr *soa, ldns_soa_serial_increment_func_t f) 394{ 395 ldns_rr_soa_increment_func_data(soa, f, NULL); 396} 397 398void 399ldns_rr_soa_increment_func_data(ldns_rr *soa, 400 ldns_soa_serial_increment_func_t f, void *data) 401{ 402 ldns_rdf *prev_soa_serial_rdf; 403 if ( !soa || !f || ldns_rr_get_type(soa) != LDNS_RR_TYPE_SOA 404 || !ldns_rr_rdf(soa, 2)) { 405 return; 406 } 407 prev_soa_serial_rdf = ldns_rr_set_rdf( 408 soa 409 , ldns_native2rdf_int32( 410 LDNS_RDF_TYPE_INT32 411 , (*f)( ldns_rdf2native_int32( 412 ldns_rr_rdf(soa, 2)) 413 , data 414 ) 415 ) 416 , 2 417 ); 418 LDNS_FREE(prev_soa_serial_rdf); 419} 420 421void 422ldns_rr_soa_increment_func_int(ldns_rr *soa, 423 ldns_soa_serial_increment_func_t f, int data) 424{ 425 ldns_rr_soa_increment_func_data(soa, f, (void *) (intptr_t) data); 426} 427 428