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