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 */ 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 postion 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 /* 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 case LDNS_SIGN_HMACMD5: 325 return len; 326 default: 327 return 0; 328 } 329 } 330 331 size_t 332 ldns_rr_dnskey_key_size(const ldns_rr *key) 333 { 334 if (!key || !ldns_rr_dnskey_key(key) 335 || !ldns_rr_dnskey_algorithm(key)) { 336 return 0; 337 } 338 return ldns_rr_dnskey_key_size_raw((unsigned char*)ldns_rdf_data(ldns_rr_dnskey_key(key)), 339 ldns_rdf_size(ldns_rr_dnskey_key(key)), 340 ldns_rdf2native_int8(ldns_rr_dnskey_algorithm(key)) 341 ); 342 } 343 344 uint32_t ldns_soa_serial_identity(uint32_t ATTR_UNUSED(unused), void *data) 345 { 346 return (uint32_t) (intptr_t) data; 347 } 348 349 uint32_t ldns_soa_serial_increment(uint32_t s, void *ATTR_UNUSED(unused)) 350 { 351 return ldns_soa_serial_increment_by(s, (void *)1); 352 } 353 354 uint32_t ldns_soa_serial_increment_by(uint32_t s, void *data) 355 { 356 return s + (intptr_t) data; 357 } 358 359 uint32_t ldns_soa_serial_datecounter(uint32_t s, void *data) 360 { 361 struct tm tm; 362 char s_str[11]; 363 int32_t new_s; 364 time_t t = data ? (time_t) (intptr_t) data : ldns_time(NULL); 365 366 (void) strftime(s_str, 11, "%Y%m%d00", localtime_r(&t, &tm)); 367 new_s = (int32_t) atoi(s_str); 368 return new_s - ((int32_t) s) <= 0 ? s+1 : ((uint32_t) new_s); 369 } 370 371 uint32_t ldns_soa_serial_unixtime(uint32_t s, void *data) 372 { 373 int32_t new_s = data ? (int32_t) (intptr_t) data 374 : (int32_t) ldns_time(NULL); 375 return new_s - ((int32_t) s) <= 0 ? s+1 : ((uint32_t) new_s); 376 } 377 378 void 379 ldns_rr_soa_increment(ldns_rr *soa) 380 { 381 ldns_rr_soa_increment_func_data(soa, ldns_soa_serial_increment, NULL); 382 } 383 384 void 385 ldns_rr_soa_increment_func(ldns_rr *soa, ldns_soa_serial_increment_func_t f) 386 { 387 ldns_rr_soa_increment_func_data(soa, f, NULL); 388 } 389 390 void 391 ldns_rr_soa_increment_func_data(ldns_rr *soa, 392 ldns_soa_serial_increment_func_t f, void *data) 393 { 394 ldns_rdf *prev_soa_serial_rdf; 395 if ( !soa || !f || ldns_rr_get_type(soa) != LDNS_RR_TYPE_SOA 396 || !ldns_rr_rdf(soa, 2)) { 397 return; 398 } 399 prev_soa_serial_rdf = ldns_rr_set_rdf( 400 soa 401 , ldns_native2rdf_int32( 402 LDNS_RDF_TYPE_INT32 403 , (*f)( ldns_rdf2native_int32( 404 ldns_rr_rdf(soa, 2)) 405 , data 406 ) 407 ) 408 , 2 409 ); 410 LDNS_FREE(prev_soa_serial_rdf); 411 } 412 413 void 414 ldns_rr_soa_increment_func_int(ldns_rr *soa, 415 ldns_soa_serial_increment_func_t f, int data) 416 { 417 ldns_rr_soa_increment_func_data(soa, f, (void *) (intptr_t) data); 418 } 419 420