1238104Sdes/* 2238104Sdes * rr_function.c 3238104Sdes * 4238104Sdes * function that operate on specific rr types 5238104Sdes * 6238104Sdes * (c) NLnet Labs, 2004-2006 7238104Sdes * See the file LICENSE for the license 8238104Sdes */ 9238104Sdes 10238104Sdes/* 11238104Sdes * These come strait from perldoc Net::DNS::RR::xxx 12238104Sdes * first the read variant, then the write. This is 13238104Sdes * not complete. 14238104Sdes */ 15238104Sdes 16238104Sdes#include <ldns/config.h> 17238104Sdes 18238104Sdes#include <ldns/ldns.h> 19238104Sdes 20238104Sdes#include <limits.h> 21238104Sdes#include <strings.h> 22238104Sdes 23238104Sdes/** 24238104Sdes * return a specific rdf 25238104Sdes * \param[in] type type of RR 26238104Sdes * \param[in] rr the rr itself 27238104Sdes * \param[in] pos at which postion to get it 28238104Sdes * \return the rdf sought 29238104Sdes */ 30238104Sdesstatic ldns_rdf * 31238104Sdesldns_rr_function(ldns_rr_type type, const ldns_rr *rr, size_t pos) 32238104Sdes{ 33238104Sdes if (!rr || ldns_rr_get_type(rr) != type) { 34238104Sdes return NULL; 35238104Sdes } 36238104Sdes return ldns_rr_rdf(rr, pos); 37238104Sdes} 38238104Sdes 39238104Sdes/** 40238104Sdes * set a specific rdf 41238104Sdes * \param[in] type type of RR 42238104Sdes * \param[in] rr the rr itself 43238104Sdes * \param[in] rdf the rdf to set 44238104Sdes * \param[in] pos at which postion to set it 45238104Sdes * \return true or false 46238104Sdes */ 47238104Sdesstatic bool 48238104Sdesldns_rr_set_function(ldns_rr_type type, ldns_rr *rr, ldns_rdf *rdf, size_t pos) 49238104Sdes{ 50238104Sdes ldns_rdf *pop; 51238104Sdes if (!rr || ldns_rr_get_type(rr) != type) { 52238104Sdes return false; 53238104Sdes } 54238104Sdes pop = ldns_rr_set_rdf(rr, rdf, pos); 55238104Sdes ldns_rdf_deep_free(pop); 56238104Sdes return true; 57238104Sdes} 58238104Sdes 59238104Sdes/* A/AAAA records */ 60238104Sdesldns_rdf * 61238104Sdesldns_rr_a_address(const ldns_rr *r) 62238104Sdes{ 63238104Sdes /* 2 types to check, cannot use the macro */ 64238104Sdes if (!r || (ldns_rr_get_type(r) != LDNS_RR_TYPE_A && 65238104Sdes ldns_rr_get_type(r) != LDNS_RR_TYPE_AAAA)) { 66238104Sdes return NULL; 67238104Sdes } 68238104Sdes return ldns_rr_rdf(r, 0); 69238104Sdes} 70238104Sdes 71238104Sdesbool 72238104Sdesldns_rr_a_set_address(ldns_rr *r, ldns_rdf *f) 73238104Sdes{ 74238104Sdes /* 2 types to check, cannot use the macro... */ 75238104Sdes ldns_rdf *pop; 76238104Sdes if (!r || (ldns_rr_get_type(r) != LDNS_RR_TYPE_A && 77238104Sdes ldns_rr_get_type(r) != LDNS_RR_TYPE_AAAA)) { 78238104Sdes return false; 79238104Sdes } 80238104Sdes pop = ldns_rr_set_rdf(r, f, 0); 81238104Sdes if (pop) { 82238104Sdes LDNS_FREE(pop); 83238104Sdes return true; 84238104Sdes } else { 85238104Sdes return false; 86238104Sdes } 87238104Sdes} 88238104Sdes 89238104Sdes/* NS record */ 90238104Sdesldns_rdf * 91238104Sdesldns_rr_ns_nsdname(const ldns_rr *r) 92238104Sdes{ 93238104Sdes return ldns_rr_function(LDNS_RR_TYPE_NS, r, 0); 94238104Sdes} 95238104Sdes 96238104Sdes/* MX record */ 97238104Sdesldns_rdf * 98238104Sdesldns_rr_mx_preference(const ldns_rr *r) 99238104Sdes{ 100238104Sdes return ldns_rr_function(LDNS_RR_TYPE_MX, r, 0); 101238104Sdes} 102238104Sdes 103238104Sdesldns_rdf * 104238104Sdesldns_rr_mx_exchange(const ldns_rr *r) 105238104Sdes{ 106238104Sdes return ldns_rr_function(LDNS_RR_TYPE_MX, r, 1); 107238104Sdes} 108238104Sdes 109238104Sdes/* RRSIG record */ 110238104Sdesldns_rdf * 111238104Sdesldns_rr_rrsig_typecovered(const ldns_rr *r) 112238104Sdes{ 113238104Sdes return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 0); 114238104Sdes} 115238104Sdes 116238104Sdesbool 117238104Sdesldns_rr_rrsig_set_typecovered(ldns_rr *r, ldns_rdf *f) 118238104Sdes{ 119238104Sdes return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 0); 120238104Sdes} 121238104Sdes 122238104Sdesldns_rdf * 123238104Sdesldns_rr_rrsig_algorithm(const ldns_rr *r) 124238104Sdes{ 125238104Sdes return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 1); 126238104Sdes} 127238104Sdes 128238104Sdesbool 129238104Sdesldns_rr_rrsig_set_algorithm(ldns_rr *r, ldns_rdf *f) 130238104Sdes{ 131238104Sdes return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 1); 132238104Sdes} 133238104Sdes 134238104Sdesldns_rdf * 135238104Sdesldns_rr_rrsig_labels(const ldns_rr *r) 136238104Sdes{ 137238104Sdes return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 2); 138238104Sdes} 139238104Sdes 140238104Sdesbool 141238104Sdesldns_rr_rrsig_set_labels(ldns_rr *r, ldns_rdf *f) 142238104Sdes{ 143238104Sdes return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 2); 144238104Sdes} 145238104Sdes 146238104Sdesldns_rdf * 147238104Sdesldns_rr_rrsig_origttl(const ldns_rr *r) 148238104Sdes{ 149238104Sdes return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 3); 150238104Sdes} 151238104Sdes 152238104Sdesbool 153238104Sdesldns_rr_rrsig_set_origttl(ldns_rr *r, ldns_rdf *f) 154238104Sdes{ 155238104Sdes return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 3); 156238104Sdes} 157238104Sdes 158238104Sdesldns_rdf * 159238104Sdesldns_rr_rrsig_expiration(const ldns_rr *r) 160238104Sdes{ 161238104Sdes return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 4); 162238104Sdes} 163238104Sdes 164238104Sdesbool 165238104Sdesldns_rr_rrsig_set_expiration(ldns_rr *r, ldns_rdf *f) 166238104Sdes{ 167238104Sdes return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 4); 168238104Sdes} 169238104Sdes 170238104Sdesldns_rdf * 171238104Sdesldns_rr_rrsig_inception(const ldns_rr *r) 172238104Sdes{ 173238104Sdes return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 5); 174238104Sdes} 175238104Sdes 176238104Sdesbool 177238104Sdesldns_rr_rrsig_set_inception(ldns_rr *r, ldns_rdf *f) 178238104Sdes{ 179238104Sdes return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 5); 180238104Sdes} 181238104Sdes 182238104Sdesldns_rdf * 183238104Sdesldns_rr_rrsig_keytag(const ldns_rr *r) 184238104Sdes{ 185238104Sdes return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 6); 186238104Sdes} 187238104Sdes 188238104Sdesbool 189238104Sdesldns_rr_rrsig_set_keytag(ldns_rr *r, ldns_rdf *f) 190238104Sdes{ 191238104Sdes return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 6); 192238104Sdes} 193238104Sdes 194238104Sdesldns_rdf * 195238104Sdesldns_rr_rrsig_signame(const ldns_rr *r) 196238104Sdes{ 197238104Sdes return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 7); 198238104Sdes} 199238104Sdes 200238104Sdesbool 201238104Sdesldns_rr_rrsig_set_signame(ldns_rr *r, ldns_rdf *f) 202238104Sdes{ 203238104Sdes return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 7); 204238104Sdes} 205238104Sdes 206238104Sdesldns_rdf * 207238104Sdesldns_rr_rrsig_sig(const ldns_rr *r) 208238104Sdes{ 209238104Sdes return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 8); 210238104Sdes} 211238104Sdes 212238104Sdesbool 213238104Sdesldns_rr_rrsig_set_sig(ldns_rr *r, ldns_rdf *f) 214238104Sdes{ 215238104Sdes return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 8); 216238104Sdes} 217238104Sdes 218238104Sdes/* DNSKEY record */ 219238104Sdesldns_rdf * 220238104Sdesldns_rr_dnskey_flags(const ldns_rr *r) 221238104Sdes{ 222238104Sdes return ldns_rr_function(LDNS_RR_TYPE_DNSKEY, r, 0); 223238104Sdes} 224238104Sdes 225238104Sdesbool 226238104Sdesldns_rr_dnskey_set_flags(ldns_rr *r, ldns_rdf *f) 227238104Sdes{ 228238104Sdes return ldns_rr_set_function(LDNS_RR_TYPE_DNSKEY, r, f, 0); 229238104Sdes} 230238104Sdes 231238104Sdesldns_rdf * 232238104Sdesldns_rr_dnskey_protocol(const ldns_rr *r) 233238104Sdes{ 234238104Sdes return ldns_rr_function(LDNS_RR_TYPE_DNSKEY, r, 1); 235238104Sdes} 236238104Sdes 237238104Sdesbool 238238104Sdesldns_rr_dnskey_set_protocol(ldns_rr *r, ldns_rdf *f) 239238104Sdes{ 240238104Sdes return ldns_rr_set_function(LDNS_RR_TYPE_DNSKEY, r, f, 1); 241238104Sdes} 242238104Sdes 243238104Sdesldns_rdf * 244238104Sdesldns_rr_dnskey_algorithm(const ldns_rr *r) 245238104Sdes{ 246238104Sdes return ldns_rr_function(LDNS_RR_TYPE_DNSKEY, r, 2); 247238104Sdes} 248238104Sdes 249238104Sdesbool 250238104Sdesldns_rr_dnskey_set_algorithm(ldns_rr *r, ldns_rdf *f) 251238104Sdes{ 252238104Sdes return ldns_rr_set_function(LDNS_RR_TYPE_DNSKEY, r, f, 2); 253238104Sdes} 254238104Sdes 255238104Sdesldns_rdf * 256238104Sdesldns_rr_dnskey_key(const ldns_rr *r) 257238104Sdes{ 258238104Sdes return ldns_rr_function(LDNS_RR_TYPE_DNSKEY, r, 3); 259238104Sdes} 260238104Sdes 261238104Sdesbool 262238104Sdesldns_rr_dnskey_set_key(ldns_rr *r, ldns_rdf *f) 263238104Sdes{ 264238104Sdes return ldns_rr_set_function(LDNS_RR_TYPE_DNSKEY, r, f, 3); 265238104Sdes} 266238104Sdes 267238104Sdessize_t 268238104Sdesldns_rr_dnskey_key_size_raw(const unsigned char* keydata, 269238104Sdes const size_t len, 270238104Sdes const ldns_algorithm alg) 271238104Sdes{ 272238104Sdes /* for DSA keys */ 273238104Sdes uint8_t t; 274238104Sdes 275238104Sdes /* for RSA keys */ 276238104Sdes uint16_t exp; 277238104Sdes uint16_t int16; 278238104Sdes 279238104Sdes switch ((ldns_signing_algorithm)alg) { 280238104Sdes case LDNS_SIGN_DSA: 281238104Sdes case LDNS_SIGN_DSA_NSEC3: 282238104Sdes if (len > 0) { 283238104Sdes t = keydata[0]; 284238104Sdes return (64 + t*8)*8; 285238104Sdes } else { 286238104Sdes return 0; 287238104Sdes } 288238104Sdes break; 289238104Sdes case LDNS_SIGN_RSAMD5: 290238104Sdes case LDNS_SIGN_RSASHA1: 291238104Sdes case LDNS_SIGN_RSASHA1_NSEC3: 292238104Sdes#ifdef USE_SHA2 293238104Sdes case LDNS_SIGN_RSASHA256: 294238104Sdes case LDNS_SIGN_RSASHA512: 295238104Sdes#endif 296238104Sdes if (len > 0) { 297238104Sdes if (keydata[0] == 0) { 298238104Sdes /* big exponent */ 299238104Sdes if (len > 3) { 300238104Sdes memmove(&int16, keydata + 1, 2); 301238104Sdes exp = ntohs(int16); 302238104Sdes return (len - exp - 3)*8; 303238104Sdes } else { 304238104Sdes return 0; 305238104Sdes } 306238104Sdes } else { 307238104Sdes exp = keydata[0]; 308238104Sdes return (len-exp-1)*8; 309238104Sdes } 310238104Sdes } else { 311238104Sdes return 0; 312238104Sdes } 313238104Sdes break; 314238104Sdes#ifdef USE_GOST 315238104Sdes case LDNS_SIGN_ECC_GOST: 316238104Sdes return 512; 317238104Sdes#endif 318238104Sdes#ifdef USE_ECDSA 319238104Sdes case LDNS_SIGN_ECDSAP256SHA256: 320238104Sdes return 256; 321238104Sdes case LDNS_SIGN_ECDSAP384SHA384: 322238104Sdes return 384; 323238104Sdes#endif 324238104Sdes case LDNS_SIGN_HMACMD5: 325238104Sdes return len; 326238104Sdes default: 327238104Sdes return 0; 328238104Sdes } 329238104Sdes} 330238104Sdes 331238104Sdessize_t 332238104Sdesldns_rr_dnskey_key_size(const ldns_rr *key) 333238104Sdes{ 334238104Sdes if (!key || !ldns_rr_dnskey_key(key) 335238104Sdes || !ldns_rr_dnskey_algorithm(key)) { 336238104Sdes return 0; 337238104Sdes } 338238104Sdes return ldns_rr_dnskey_key_size_raw((unsigned char*)ldns_rdf_data(ldns_rr_dnskey_key(key)), 339238104Sdes ldns_rdf_size(ldns_rr_dnskey_key(key)), 340238104Sdes ldns_rdf2native_int8(ldns_rr_dnskey_algorithm(key)) 341238104Sdes ); 342238104Sdes} 343238104Sdes 344238104Sdesuint32_t ldns_soa_serial_identity(uint32_t ATTR_UNUSED(unused), void *data) 345238104Sdes{ 346238104Sdes return (uint32_t) (intptr_t) data; 347238104Sdes} 348238104Sdes 349238104Sdesuint32_t ldns_soa_serial_increment(uint32_t s, void *ATTR_UNUSED(unused)) 350238104Sdes{ 351238104Sdes return ldns_soa_serial_increment_by(s, (void *)1); 352238104Sdes} 353238104Sdes 354238104Sdesuint32_t ldns_soa_serial_increment_by(uint32_t s, void *data) 355238104Sdes{ 356238104Sdes return s + (intptr_t) data; 357238104Sdes} 358238104Sdes 359238104Sdesuint32_t ldns_soa_serial_datecounter(uint32_t s, void *data) 360238104Sdes{ 361238104Sdes struct tm tm; 362238104Sdes char s_str[11]; 363238104Sdes int32_t new_s; 364238104Sdes time_t t = data ? (time_t) (intptr_t) data : ldns_time(NULL); 365238104Sdes 366238104Sdes (void) strftime(s_str, 11, "%Y%m%d00", localtime_r(&t, &tm)); 367238104Sdes new_s = (int32_t) atoi(s_str); 368238104Sdes return new_s - ((int32_t) s) <= 0 ? s+1 : ((uint32_t) new_s); 369238104Sdes} 370238104Sdes 371238104Sdesuint32_t ldns_soa_serial_unixtime(uint32_t s, void *data) 372238104Sdes{ 373238104Sdes int32_t new_s = data ? (int32_t) (intptr_t) data 374238104Sdes : (int32_t) ldns_time(NULL); 375238104Sdes return new_s - ((int32_t) s) <= 0 ? s+1 : ((uint32_t) new_s); 376238104Sdes} 377238104Sdes 378238104Sdesvoid 379238104Sdesldns_rr_soa_increment(ldns_rr *soa) 380238104Sdes{ 381238104Sdes ldns_rr_soa_increment_func_data(soa, ldns_soa_serial_increment, NULL); 382238104Sdes} 383238104Sdes 384238104Sdesvoid 385238104Sdesldns_rr_soa_increment_func(ldns_rr *soa, ldns_soa_serial_increment_func_t f) 386238104Sdes{ 387238104Sdes ldns_rr_soa_increment_func_data(soa, f, NULL); 388238104Sdes} 389238104Sdes 390238104Sdesvoid 391238104Sdesldns_rr_soa_increment_func_data(ldns_rr *soa, 392238104Sdes ldns_soa_serial_increment_func_t f, void *data) 393238104Sdes{ 394238104Sdes ldns_rdf *prev_soa_serial_rdf; 395238104Sdes if ( !soa || !f || ldns_rr_get_type(soa) != LDNS_RR_TYPE_SOA 396238104Sdes || !ldns_rr_rdf(soa, 2)) { 397238104Sdes return; 398238104Sdes } 399238104Sdes prev_soa_serial_rdf = ldns_rr_set_rdf( 400238104Sdes soa 401238104Sdes , ldns_native2rdf_int32( 402238104Sdes LDNS_RDF_TYPE_INT32 403238104Sdes , (*f)( ldns_rdf2native_int32( 404238104Sdes ldns_rr_rdf(soa, 2)) 405238104Sdes , data 406238104Sdes ) 407238104Sdes ) 408238104Sdes , 2 409238104Sdes ); 410238104Sdes LDNS_FREE(prev_soa_serial_rdf); 411238104Sdes} 412238104Sdes 413238104Sdesvoid 414238104Sdesldns_rr_soa_increment_func_int(ldns_rr *soa, 415238104Sdes ldns_soa_serial_increment_func_t f, int data) 416238104Sdes{ 417238104Sdes ldns_rr_soa_increment_func_data(soa, f, (void *) (intptr_t) data); 418238104Sdes} 419238104Sdes 420