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 * 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 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 * 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 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 * 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 * 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 * 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 * 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 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 * 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 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 * 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 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 * 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 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 * 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 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 * 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 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 * 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 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 * 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 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 * 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 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 * 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 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 * 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 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 * 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 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 * 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 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 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 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 356 uint32_t ldns_soa_serial_identity(uint32_t ATTR_UNUSED(unused), void *data) 357 { 358 return (uint32_t) (intptr_t) data; 359 } 360 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 366 uint32_t ldns_soa_serial_increment_by(uint32_t s, void *data) 367 { 368 return s + (intptr_t) data; 369 } 370 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 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 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 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 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 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