1 /* 2 * rdata.c 3 * 4 * rdata implementation 5 * 6 * a Net::DNS like library for C 7 * 8 * (c) NLnet Labs, 2004-2006 9 * 10 * See the file LICENSE for the license 11 */ 12 13 #include <ldns/config.h> 14 15 #include <ldns/ldns.h> 16 17 /* 18 * Access functions 19 * do this as functions to get type checking 20 */ 21 22 /* read */ 23 size_t 24 ldns_rdf_size(const ldns_rdf *rd) 25 { 26 assert(rd != NULL); 27 return rd->_size; 28 } 29 30 ldns_rdf_type 31 ldns_rdf_get_type(const ldns_rdf *rd) 32 { 33 assert(rd != NULL); 34 return rd->_type; 35 } 36 37 uint8_t * 38 ldns_rdf_data(const ldns_rdf *rd) 39 { 40 assert(rd != NULL); 41 return rd->_data; 42 } 43 44 /* write */ 45 void 46 ldns_rdf_set_size(ldns_rdf *rd, size_t size) 47 { 48 assert(rd != NULL); 49 rd->_size = size; 50 } 51 52 void 53 ldns_rdf_set_type(ldns_rdf *rd, ldns_rdf_type type) 54 { 55 assert(rd != NULL); 56 rd->_type = type; 57 } 58 59 void 60 ldns_rdf_set_data(ldns_rdf *rd, void *data) 61 { 62 /* only copy the pointer */ 63 assert(rd != NULL); 64 rd->_data = data; 65 } 66 67 /* for types that allow it, return 68 * the native/host order type */ 69 uint8_t 70 ldns_rdf2native_int8(const ldns_rdf *rd) 71 { 72 uint8_t data; 73 74 /* only allow 8 bit rdfs */ 75 if (ldns_rdf_size(rd) != LDNS_RDF_SIZE_BYTE) { 76 return 0; 77 } 78 79 memcpy(&data, ldns_rdf_data(rd), sizeof(data)); 80 return data; 81 } 82 83 uint16_t 84 ldns_rdf2native_int16(const ldns_rdf *rd) 85 { 86 uint16_t data; 87 88 /* only allow 16 bit rdfs */ 89 if (ldns_rdf_size(rd) != LDNS_RDF_SIZE_WORD) { 90 return 0; 91 } 92 93 memcpy(&data, ldns_rdf_data(rd), sizeof(data)); 94 return ntohs(data); 95 } 96 97 uint32_t 98 ldns_rdf2native_int32(const ldns_rdf *rd) 99 { 100 uint32_t data; 101 102 /* only allow 32 bit rdfs */ 103 if (ldns_rdf_size(rd) != LDNS_RDF_SIZE_DOUBLEWORD) { 104 return 0; 105 } 106 107 memcpy(&data, ldns_rdf_data(rd), sizeof(data)); 108 return ntohl(data); 109 } 110 111 time_t 112 ldns_rdf2native_time_t(const ldns_rdf *rd) 113 { 114 uint32_t data; 115 116 switch(ldns_rdf_get_type(rd)) { 117 case LDNS_RDF_TYPE_TIME: 118 memcpy(&data, ldns_rdf_data(rd), sizeof(data)); 119 return (time_t)ntohl(data); 120 default: 121 return 0; 122 } 123 } 124 125 ldns_rdf * 126 ldns_native2rdf_int8(ldns_rdf_type type, uint8_t value) 127 { 128 return ldns_rdf_new_frm_data(type, LDNS_RDF_SIZE_BYTE, &value); 129 } 130 131 ldns_rdf * 132 ldns_native2rdf_int16(ldns_rdf_type type, uint16_t value) 133 { 134 uint16_t *rdf_data = LDNS_XMALLOC(uint16_t, 1); 135 ldns_rdf* rdf; 136 if (!rdf_data) { 137 return NULL; 138 } 139 ldns_write_uint16(rdf_data, value); 140 rdf = ldns_rdf_new(type, LDNS_RDF_SIZE_WORD, rdf_data); 141 if(!rdf) 142 LDNS_FREE(rdf_data); 143 return rdf; 144 } 145 146 ldns_rdf * 147 ldns_native2rdf_int32(ldns_rdf_type type, uint32_t value) 148 { 149 uint32_t *rdf_data = LDNS_XMALLOC(uint32_t, 1); 150 ldns_rdf* rdf; 151 if (!rdf_data) { 152 return NULL; 153 } 154 ldns_write_uint32(rdf_data, value); 155 rdf = ldns_rdf_new(type, LDNS_RDF_SIZE_DOUBLEWORD, rdf_data); 156 if(!rdf) 157 LDNS_FREE(rdf_data); 158 return rdf; 159 } 160 161 ldns_rdf * 162 ldns_native2rdf_int16_data(size_t size, uint8_t *data) 163 { 164 uint8_t *rdf_data = LDNS_XMALLOC(uint8_t, size + 2); 165 ldns_rdf* rdf; 166 if (!rdf_data) { 167 return NULL; 168 } 169 ldns_write_uint16(rdf_data, size); 170 memcpy(rdf_data + 2, data, size); 171 rdf = ldns_rdf_new(LDNS_RDF_TYPE_INT16_DATA, size + 2, rdf_data); 172 if(!rdf) 173 LDNS_FREE(rdf_data); 174 return rdf; 175 } 176 177 /* note: data must be allocated memory */ 178 ldns_rdf * 179 ldns_rdf_new(ldns_rdf_type type, size_t size, void *data) 180 { 181 ldns_rdf *rd; 182 rd = LDNS_MALLOC(ldns_rdf); 183 if (!rd) { 184 return NULL; 185 } 186 ldns_rdf_set_size(rd, size); 187 ldns_rdf_set_type(rd, type); 188 ldns_rdf_set_data(rd, data); 189 return rd; 190 } 191 192 ldns_rdf * 193 ldns_rdf_new_frm_data(ldns_rdf_type type, size_t size, const void *data) 194 { 195 ldns_rdf *rdf; 196 197 /* if the size is too big, fail */ 198 if (size > LDNS_MAX_RDFLEN) { 199 return NULL; 200 } 201 202 /* allocate space */ 203 rdf = LDNS_MALLOC(ldns_rdf); 204 if (!rdf) { 205 return NULL; 206 } 207 rdf->_data = LDNS_XMALLOC(uint8_t, size); 208 if (!rdf->_data) { 209 LDNS_FREE(rdf); 210 return NULL; 211 } 212 213 /* set the values */ 214 ldns_rdf_set_type(rdf, type); 215 ldns_rdf_set_size(rdf, size); 216 memcpy(rdf->_data, data, size); 217 218 return rdf; 219 } 220 221 ldns_rdf * 222 ldns_rdf_clone(const ldns_rdf *rd) 223 { 224 assert(rd != NULL); 225 return (ldns_rdf_new_frm_data( ldns_rdf_get_type(rd), 226 ldns_rdf_size(rd), ldns_rdf_data(rd))); 227 } 228 229 void 230 ldns_rdf_deep_free(ldns_rdf *rd) 231 { 232 if (rd) { 233 if (rd->_data) { 234 LDNS_FREE(rd->_data); 235 } 236 LDNS_FREE(rd); 237 } 238 } 239 240 void 241 ldns_rdf_free(ldns_rdf *rd) 242 { 243 if (rd) { 244 LDNS_FREE(rd); 245 } 246 } 247 248 ldns_rdf * 249 ldns_rdf_new_frm_str(ldns_rdf_type type, const char *str) 250 { 251 ldns_rdf *rdf = NULL; 252 ldns_status status; 253 254 switch (type) { 255 case LDNS_RDF_TYPE_DNAME: 256 status = ldns_str2rdf_dname(&rdf, str); 257 break; 258 case LDNS_RDF_TYPE_INT8: 259 status = ldns_str2rdf_int8(&rdf, str); 260 break; 261 case LDNS_RDF_TYPE_INT16: 262 status = ldns_str2rdf_int16(&rdf, str); 263 break; 264 case LDNS_RDF_TYPE_INT32: 265 status = ldns_str2rdf_int32(&rdf, str); 266 break; 267 case LDNS_RDF_TYPE_A: 268 status = ldns_str2rdf_a(&rdf, str); 269 break; 270 case LDNS_RDF_TYPE_AAAA: 271 status = ldns_str2rdf_aaaa(&rdf, str); 272 break; 273 case LDNS_RDF_TYPE_STR: 274 status = ldns_str2rdf_str(&rdf, str); 275 break; 276 case LDNS_RDF_TYPE_APL: 277 status = ldns_str2rdf_apl(&rdf, str); 278 break; 279 case LDNS_RDF_TYPE_B64: 280 status = ldns_str2rdf_b64(&rdf, str); 281 break; 282 case LDNS_RDF_TYPE_B32_EXT: 283 status = ldns_str2rdf_b32_ext(&rdf, str); 284 break; 285 case LDNS_RDF_TYPE_HEX: 286 status = ldns_str2rdf_hex(&rdf, str); 287 break; 288 case LDNS_RDF_TYPE_NSEC: 289 status = ldns_str2rdf_nsec(&rdf, str); 290 break; 291 case LDNS_RDF_TYPE_TYPE: 292 status = ldns_str2rdf_type(&rdf, str); 293 break; 294 case LDNS_RDF_TYPE_CLASS: 295 status = ldns_str2rdf_class(&rdf, str); 296 break; 297 case LDNS_RDF_TYPE_CERT_ALG: 298 status = ldns_str2rdf_cert_alg(&rdf, str); 299 break; 300 case LDNS_RDF_TYPE_ALG: 301 status = ldns_str2rdf_alg(&rdf, str); 302 break; 303 case LDNS_RDF_TYPE_UNKNOWN: 304 status = ldns_str2rdf_unknown(&rdf, str); 305 break; 306 case LDNS_RDF_TYPE_TIME: 307 status = ldns_str2rdf_time(&rdf, str); 308 break; 309 case LDNS_RDF_TYPE_PERIOD: 310 status = ldns_str2rdf_period(&rdf, str); 311 break; 312 case LDNS_RDF_TYPE_TSIG: 313 status = ldns_str2rdf_tsig(&rdf, str); 314 break; 315 case LDNS_RDF_TYPE_SERVICE: 316 status = ldns_str2rdf_service(&rdf, str); 317 break; 318 case LDNS_RDF_TYPE_LOC: 319 status = ldns_str2rdf_loc(&rdf, str); 320 break; 321 case LDNS_RDF_TYPE_WKS: 322 status = ldns_str2rdf_wks(&rdf, str); 323 break; 324 case LDNS_RDF_TYPE_NSAP: 325 status = ldns_str2rdf_nsap(&rdf, str); 326 break; 327 case LDNS_RDF_TYPE_ATMA: 328 status = ldns_str2rdf_atma(&rdf, str); 329 break; 330 case LDNS_RDF_TYPE_IPSECKEY: 331 status = ldns_str2rdf_ipseckey(&rdf, str); 332 break; 333 case LDNS_RDF_TYPE_NSEC3_SALT: 334 status = ldns_str2rdf_nsec3_salt(&rdf, str); 335 break; 336 case LDNS_RDF_TYPE_NSEC3_NEXT_OWNER: 337 status = ldns_str2rdf_b32_ext(&rdf, str); 338 break; 339 case LDNS_RDF_TYPE_NONE: 340 default: 341 /* default default ??? */ 342 status = LDNS_STATUS_ERR; 343 break; 344 } 345 if (LDNS_STATUS_OK == status) { 346 ldns_rdf_set_type(rdf, type); 347 return rdf; 348 } 349 if (rdf) { 350 LDNS_FREE(rdf); 351 } 352 return NULL; 353 } 354 355 ldns_status 356 ldns_rdf_new_frm_fp(ldns_rdf **rdf, ldns_rdf_type type, FILE *fp) 357 { 358 return ldns_rdf_new_frm_fp_l(rdf, type, fp, NULL); 359 } 360 361 ldns_status 362 ldns_rdf_new_frm_fp_l(ldns_rdf **rdf, ldns_rdf_type type, FILE *fp, int *line_nr) 363 { 364 char *line; 365 ldns_rdf *r; 366 ssize_t t; 367 368 line = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1); 369 if (!line) { 370 return LDNS_STATUS_MEM_ERR; 371 } 372 373 /* read an entire line in from the file */ 374 if ((t = ldns_fget_token_l(fp, line, LDNS_PARSE_SKIP_SPACE, 0, line_nr)) == -1 || t == 0) { 375 LDNS_FREE(line); 376 return LDNS_STATUS_SYNTAX_RDATA_ERR; 377 } 378 r = ldns_rdf_new_frm_str(type, (const char*) line); 379 LDNS_FREE(line); 380 if (rdf) { 381 *rdf = r; 382 return LDNS_STATUS_OK; 383 } else { 384 return LDNS_STATUS_NULL; 385 } 386 } 387 388 ldns_rdf * 389 ldns_rdf_address_reverse(ldns_rdf *rd) 390 { 391 uint8_t buf_4[LDNS_IP4ADDRLEN]; 392 uint8_t buf_6[LDNS_IP6ADDRLEN * 2]; 393 ldns_rdf *rev; 394 ldns_rdf *in_addr; 395 ldns_rdf *ret_dname; 396 uint8_t octet; 397 uint8_t nnibble; 398 uint8_t nibble; 399 uint8_t i, j; 400 401 char *char_dname; 402 int nbit; 403 404 if (ldns_rdf_get_type(rd) != LDNS_RDF_TYPE_A && 405 ldns_rdf_get_type(rd) != LDNS_RDF_TYPE_AAAA) { 406 return NULL; 407 } 408 409 in_addr = NULL; 410 ret_dname = NULL; 411 412 switch(ldns_rdf_get_type(rd)) { 413 case LDNS_RDF_TYPE_A: 414 /* the length of the buffer is 4 */ 415 buf_4[3] = ldns_rdf_data(rd)[0]; 416 buf_4[2] = ldns_rdf_data(rd)[1]; 417 buf_4[1] = ldns_rdf_data(rd)[2]; 418 buf_4[0] = ldns_rdf_data(rd)[3]; 419 in_addr = ldns_dname_new_frm_str("in-addr.arpa."); 420 if (!in_addr) { 421 return NULL; 422 } 423 /* make a new rdf and convert that back */ 424 rev = ldns_rdf_new_frm_data( LDNS_RDF_TYPE_A, 425 LDNS_IP4ADDRLEN, (void*)&buf_4); 426 if (!rev) { 427 LDNS_FREE(in_addr); 428 return NULL; 429 } 430 431 /* convert rev to a string */ 432 char_dname = ldns_rdf2str(rev); 433 if (!char_dname) { 434 LDNS_FREE(in_addr); 435 ldns_rdf_deep_free(rev); 436 return NULL; 437 } 438 /* transform back to rdf with type dname */ 439 ret_dname = ldns_dname_new_frm_str(char_dname); 440 if (!ret_dname) { 441 LDNS_FREE(in_addr); 442 ldns_rdf_deep_free(rev); 443 LDNS_FREE(char_dname); 444 return NULL; 445 } 446 /* not needed anymore */ 447 ldns_rdf_deep_free(rev); 448 LDNS_FREE(char_dname); 449 break; 450 case LDNS_RDF_TYPE_AAAA: 451 /* some foo magic to reverse the nibbles ... */ 452 453 for (nbit = 127; nbit >= 0; nbit = nbit - 4) { 454 /* calculate octett (8 bit) */ 455 octet = ( ((unsigned int) nbit) & 0x78) >> 3; 456 /* calculate nibble */ 457 nnibble = ( ((unsigned int) nbit) & 0x04) >> 2; 458 /* extract nibble */ 459 nibble = (ldns_rdf_data(rd)[octet] & ( 0xf << (4 * (1 - 460 nnibble)) ) ) >> ( 4 * (1 - 461 nnibble)); 462 463 buf_6[(LDNS_IP6ADDRLEN * 2 - 1) - 464 (octet * 2 + nnibble)] = 465 (uint8_t)ldns_int_to_hexdigit((int)nibble); 466 } 467 468 char_dname = LDNS_XMALLOC(char, (LDNS_IP6ADDRLEN * 4)); 469 if (!char_dname) { 470 return NULL; 471 } 472 char_dname[LDNS_IP6ADDRLEN * 4 - 1] = '\0'; /* closure */ 473 474 /* walk the string and add . 's */ 475 for (i = 0, j = 0; i < LDNS_IP6ADDRLEN * 2; i++, j = j + 2) { 476 char_dname[j] = (char)buf_6[i]; 477 if (i != LDNS_IP6ADDRLEN * 2 - 1) { 478 char_dname[j + 1] = '.'; 479 } 480 } 481 in_addr = ldns_dname_new_frm_str("ip6.arpa."); 482 if (!in_addr) { 483 LDNS_FREE(char_dname); 484 return NULL; 485 } 486 487 /* convert rev to a string */ 488 ret_dname = ldns_dname_new_frm_str(char_dname); 489 LDNS_FREE(char_dname); 490 if (!ret_dname) { 491 ldns_rdf_deep_free(in_addr); 492 return NULL; 493 } 494 break; 495 default: 496 break; 497 } 498 /* add the suffix */ 499 rev = ldns_dname_cat_clone(ret_dname, in_addr); 500 501 ldns_rdf_deep_free(ret_dname); 502 ldns_rdf_deep_free(in_addr); 503 return rev; 504 } 505 506 ldns_status 507 ldns_octet(char *word, size_t *length) 508 { 509 char *s; 510 char *p; 511 *length = 0; 512 513 for (s = p = word; *s != '\0'; s++,p++) { 514 switch (*s) { 515 case '.': 516 if (s[1] == '.') { 517 return LDNS_STATUS_EMPTY_LABEL; 518 } 519 *p = *s; 520 (*length)++; 521 break; 522 case '\\': 523 if ('0' <= s[1] && s[1] <= '9' && 524 '0' <= s[2] && s[2] <= '9' && 525 '0' <= s[3] && s[3] <= '9') { 526 /* \DDD seen */ 527 int val = ((s[1] - '0') * 100 + 528 (s[2] - '0') * 10 + (s[3] - '0')); 529 530 if (0 <= val && val <= 255) { 531 /* this also handles \0 */ 532 s += 3; 533 *p = val; 534 (*length)++; 535 } else { 536 return LDNS_STATUS_DDD_OVERFLOW; 537 } 538 } else { 539 /* an espaced character, like \<space> ? 540 * remove the '\' keep the rest */ 541 *p = *++s; 542 (*length)++; 543 } 544 break; 545 case '\"': 546 /* non quoted " Is either first or the last character in 547 * the string */ 548 549 *p = *++s; /* skip it */ 550 (*length)++; 551 /* I'm not sure if this is needed in libdns... MG */ 552 if ( *s == '\0' ) { 553 /* ok, it was the last one */ 554 *p = '\0'; 555 return LDNS_STATUS_OK; 556 } 557 break; 558 default: 559 *p = *s; 560 (*length)++; 561 break; 562 } 563 } 564 *p = '\0'; 565 return LDNS_STATUS_OK; 566 } 567 568 int 569 ldns_rdf_compare(const ldns_rdf *rd1, const ldns_rdf *rd2) 570 { 571 uint16_t i1, i2, i; 572 uint8_t *d1, *d2; 573 574 /* only when both are not NULL we can say anything about them */ 575 if (!rd1 && !rd2) { 576 return 0; 577 } 578 if (!rd1 || !rd2) { 579 return -1; 580 } 581 i1 = ldns_rdf_size(rd1); 582 i2 = ldns_rdf_size(rd2); 583 584 if (i1 < i2) { 585 return -1; 586 } else if (i1 > i2) { 587 return +1; 588 } else { 589 d1 = (uint8_t*)ldns_rdf_data(rd1); 590 d2 = (uint8_t*)ldns_rdf_data(rd2); 591 for(i = 0; i < i1; i++) { 592 if (d1[i] < d2[i]) { 593 return -1; 594 } else if (d1[i] > d2[i]) { 595 return +1; 596 } 597 } 598 } 599 return 0; 600 } 601 602 uint32_t 603 ldns_str2period(const char *nptr, const char **endptr) 604 { 605 int sign = 0; 606 uint32_t i = 0; 607 uint32_t seconds = 0; 608 609 for(*endptr = nptr; **endptr; (*endptr)++) { 610 switch (**endptr) { 611 case ' ': 612 case '\t': 613 break; 614 case '-': 615 if(sign == 0) { 616 sign = -1; 617 } else { 618 return seconds; 619 } 620 break; 621 case '+': 622 if(sign == 0) { 623 sign = 1; 624 } else { 625 return seconds; 626 } 627 break; 628 case 's': 629 case 'S': 630 seconds += i; 631 i = 0; 632 break; 633 case 'm': 634 case 'M': 635 seconds += i * 60; 636 i = 0; 637 break; 638 case 'h': 639 case 'H': 640 seconds += i * 60 * 60; 641 i = 0; 642 break; 643 case 'd': 644 case 'D': 645 seconds += i * 60 * 60 * 24; 646 i = 0; 647 break; 648 case 'w': 649 case 'W': 650 seconds += i * 60 * 60 * 24 * 7; 651 i = 0; 652 break; 653 case '0': 654 case '1': 655 case '2': 656 case '3': 657 case '4': 658 case '5': 659 case '6': 660 case '7': 661 case '8': 662 case '9': 663 i *= 10; 664 i += (**endptr - '0'); 665 break; 666 default: 667 seconds += i; 668 /* disregard signedness */ 669 return seconds; 670 } 671 } 672 seconds += i; 673 /* disregard signedness */ 674 return seconds; 675 } 676