1 /* 2 * str2host.c 3 * 4 * conversion routines from the presentation format 5 * to the host format 6 * 7 * a Net::DNS like library for C 8 * 9 * (c) NLnet Labs, 2004-2006 10 * 11 * See the file LICENSE for the license 12 */ 13 #include <ldns/config.h> 14 15 #include <ldns/ldns.h> 16 17 #ifdef HAVE_SYS_SOCKET_H 18 #include <sys/socket.h> 19 #endif 20 #ifdef HAVE_ARPA_INET_H 21 #include <arpa/inet.h> 22 #endif 23 #include <time.h> 24 25 #include <errno.h> 26 #ifdef HAVE_NETDB_H 27 #include <netdb.h> 28 #endif 29 30 #include <limits.h> 31 #ifdef HAVE_SYS_PARAM_H 32 #include <sys/param.h> 33 #endif 34 35 ldns_status 36 ldns_str2rdf_int16(ldns_rdf **rd, const char *shortstr) 37 { 38 char *end = NULL; 39 uint16_t *r; 40 r = LDNS_MALLOC(uint16_t); 41 if(!r) return LDNS_STATUS_MEM_ERR; 42 43 *r = htons((uint16_t)strtol((char *)shortstr, &end, 10)); 44 45 if(*end != 0) { 46 LDNS_FREE(r); 47 return LDNS_STATUS_INVALID_INT; 48 } else { 49 *rd = ldns_rdf_new_frm_data( 50 LDNS_RDF_TYPE_INT16, sizeof(uint16_t), r); 51 LDNS_FREE(r); 52 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 53 } 54 } 55 56 ldns_status 57 ldns_str2rdf_time(ldns_rdf **rd, const char *time) 58 { 59 /* convert a time YYYYDDMMHHMMSS to wireformat */ 60 uint16_t *r = NULL; 61 struct tm tm; 62 uint32_t l; 63 char *end; 64 65 /* Try to scan the time... */ 66 r = (uint16_t*)LDNS_MALLOC(uint32_t); 67 if(!r) return LDNS_STATUS_MEM_ERR; 68 69 memset(&tm, 0, sizeof(tm)); 70 71 if (strlen(time) == 14 && 72 sscanf(time, "%4d%2d%2d%2d%2d%2d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) == 6 73 ) { 74 tm.tm_year -= 1900; 75 tm.tm_mon--; 76 /* Check values */ 77 if (tm.tm_year < 70) { 78 goto bad_format; 79 } 80 if (tm.tm_mon < 0 || tm.tm_mon > 11) { 81 goto bad_format; 82 } 83 if (tm.tm_mday < 1 || tm.tm_mday > 31) { 84 goto bad_format; 85 } 86 87 if (tm.tm_hour < 0 || tm.tm_hour > 23) { 88 goto bad_format; 89 } 90 91 if (tm.tm_min < 0 || tm.tm_min > 59) { 92 goto bad_format; 93 } 94 95 if (tm.tm_sec < 0 || tm.tm_sec > 59) { 96 goto bad_format; 97 } 98 99 l = htonl(ldns_mktime_from_utc(&tm)); 100 memcpy(r, &l, sizeof(uint32_t)); 101 *rd = ldns_rdf_new_frm_data( 102 LDNS_RDF_TYPE_TIME, sizeof(uint32_t), r); 103 LDNS_FREE(r); 104 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 105 } else { 106 /* handle it as 32 bits timestamp */ 107 l = htonl((uint32_t)strtol((char*)time, &end, 10)); 108 if(*end != 0) { 109 LDNS_FREE(r); 110 return LDNS_STATUS_ERR; 111 } else { 112 memcpy(r, &l, sizeof(uint32_t)); 113 *rd = ldns_rdf_new_frm_data( 114 LDNS_RDF_TYPE_INT32, sizeof(uint32_t), r); 115 LDNS_FREE(r); 116 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 117 } 118 } 119 120 bad_format: 121 LDNS_FREE(r); 122 return LDNS_STATUS_INVALID_TIME; 123 } 124 125 ldns_status 126 ldns_str2rdf_nsec3_salt(ldns_rdf **rd, const char *salt_str) 127 { 128 uint8_t salt_length; 129 int c; 130 int salt_length_str; 131 132 uint8_t *salt; 133 uint8_t *data; 134 if(rd == NULL) { 135 return LDNS_STATUS_NULL; 136 } 137 138 salt_length_str = (int)strlen(salt_str); 139 if (salt_length_str == 1 && salt_str[0] == '-') { 140 salt_length_str = 0; 141 } else if (salt_length_str % 2 != 0) { 142 return LDNS_STATUS_INVALID_HEX; 143 } 144 if (salt_length_str > 512) { 145 return LDNS_STATUS_INVALID_HEX; 146 } 147 148 salt = LDNS_XMALLOC(uint8_t, salt_length_str / 2); 149 if(!salt) { 150 return LDNS_STATUS_MEM_ERR; 151 } 152 for (c = 0; c < salt_length_str; c += 2) { 153 if (isxdigit((int) salt_str[c]) && isxdigit((int) salt_str[c+1])) { 154 salt[c/2] = (uint8_t) ldns_hexdigit_to_int(salt_str[c]) * 16 + 155 ldns_hexdigit_to_int(salt_str[c+1]); 156 } else { 157 LDNS_FREE(salt); 158 return LDNS_STATUS_INVALID_HEX; 159 } 160 } 161 salt_length = (uint8_t) (salt_length_str / 2); 162 163 data = LDNS_XMALLOC(uint8_t, 1 + salt_length); 164 if(!data) { 165 LDNS_FREE(salt); 166 return LDNS_STATUS_MEM_ERR; 167 } 168 data[0] = salt_length; 169 memcpy(&data[1], salt, salt_length); 170 *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_NSEC3_SALT, 1 + salt_length, data); 171 LDNS_FREE(data); 172 LDNS_FREE(salt); 173 174 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 175 } 176 177 ldns_status 178 ldns_str2rdf_period(ldns_rdf **rd,const char *period) 179 { 180 uint32_t p; 181 const char *end; 182 183 /* Allocate required space... */ 184 p = ldns_str2period(period, &end); 185 186 if (*end != 0) { 187 return LDNS_STATUS_ERR; 188 } else { 189 p = (uint32_t) htonl(p); 190 *rd = ldns_rdf_new_frm_data( 191 LDNS_RDF_TYPE_PERIOD, sizeof(uint32_t), &p); 192 } 193 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 194 } 195 196 ldns_status 197 ldns_str2rdf_int32(ldns_rdf **rd, const char *longstr) 198 { 199 char *end; 200 uint16_t *r = NULL; 201 uint32_t l; 202 203 r = (uint16_t*)LDNS_MALLOC(uint32_t); 204 if(!r) return LDNS_STATUS_MEM_ERR; 205 errno = 0; /* must set to zero before call, 206 note race condition on errno */ 207 if(*longstr == '-') 208 l = htonl((uint32_t)strtol((char*)longstr, &end, 10)); 209 else l = htonl((uint32_t)strtoul((char*)longstr, &end, 10)); 210 211 if(*end != 0) { 212 LDNS_FREE(r); 213 return LDNS_STATUS_ERR; 214 } else { 215 if (errno == ERANGE) { 216 LDNS_FREE(r); 217 return LDNS_STATUS_SYNTAX_INTEGER_OVERFLOW; 218 } 219 memcpy(r, &l, sizeof(uint32_t)); 220 *rd = ldns_rdf_new_frm_data( 221 LDNS_RDF_TYPE_INT32, sizeof(uint32_t), r); 222 LDNS_FREE(r); 223 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 224 } 225 } 226 227 ldns_status 228 ldns_str2rdf_int8(ldns_rdf **rd, const char *bytestr) 229 { 230 char *end; 231 uint8_t *r = NULL; 232 233 r = LDNS_MALLOC(uint8_t); 234 if(!r) return LDNS_STATUS_MEM_ERR; 235 236 *r = (uint8_t)strtol((char*)bytestr, &end, 10); 237 238 if(*end != 0) { 239 LDNS_FREE(r); 240 return LDNS_STATUS_ERR; 241 } else { 242 *rd = ldns_rdf_new_frm_data( 243 LDNS_RDF_TYPE_INT8, sizeof(uint8_t), r); 244 LDNS_FREE(r); 245 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 246 } 247 } 248 249 250 /* 251 * Checks whether the escaped value at **s is an decimal value or 252 * a 'normally' escaped character (and not eos) 253 * 254 * The string pointer at *s is increased by either 0 (on error), 1 (on 255 * normal escapes), or 3 (on decimals) 256 * 257 * Returns the number of bytes read from the escaped string, or 258 * 0 on error 259 */ 260 INLINE bool 261 parse_escape(uint8_t *ch_p, const char** str_p) 262 { 263 uint16_t val; 264 265 if ((*str_p)[0] && isdigit((unsigned char)(*str_p)[0]) && 266 (*str_p)[1] && isdigit((unsigned char)(*str_p)[1]) && 267 (*str_p)[2] && isdigit((unsigned char)(*str_p)[2])) { 268 269 val = (uint16_t)(((*str_p)[0] - '0') * 100 + 270 ((*str_p)[1] - '0') * 10 + 271 ((*str_p)[2] - '0')); 272 273 if (val > 255) { 274 goto error; 275 } 276 *ch_p = (uint8_t)val; 277 *str_p += 3; 278 return true; 279 280 } else if ((*str_p)[0] && !isdigit((unsigned char)(*str_p)[0])) { 281 282 *ch_p = (uint8_t)*(*str_p)++; 283 return true; 284 } 285 error: 286 *str_p = NULL; 287 return false; /* LDNS_STATUS_SYNTAX_BAD_ESCAPE */ 288 } 289 290 INLINE bool 291 parse_char(uint8_t *ch_p, const char** str_p) 292 { 293 switch (**str_p) { 294 295 case '\0': return false; 296 297 case '\\': *str_p += 1; 298 return parse_escape(ch_p, str_p); 299 300 default: *ch_p = (uint8_t)*(*str_p)++; 301 return true; 302 } 303 } 304 305 /* 306 * No special care is taken, all dots are translated into 307 * label seperators. 308 * Could be made more efficient....we do 3 memcpy's in total... 309 */ 310 ldns_status 311 ldns_str2rdf_dname(ldns_rdf **d, const char *str) 312 { 313 size_t len; 314 315 const char *s; 316 uint8_t *q, *pq, label_len; 317 uint8_t buf[LDNS_MAX_DOMAINLEN + 1]; 318 *d = NULL; 319 320 len = strlen((char*)str); 321 /* octet representation can make strings a lot longer than actual length */ 322 if (len > LDNS_MAX_DOMAINLEN * 4) { 323 return LDNS_STATUS_DOMAINNAME_OVERFLOW; 324 } 325 if (0 == len) { 326 return LDNS_STATUS_DOMAINNAME_UNDERFLOW; 327 } 328 329 /* root label */ 330 if (1 == len && *str == '.') { 331 *d = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME, 1, "\0"); 332 return LDNS_STATUS_OK; 333 } 334 335 /* get on with the rest */ 336 337 /* s is on the current character in the string 338 * pq points to where the labellength is going to go 339 * label_len keeps track of the current label's length 340 * q builds the dname inside the buf array 341 */ 342 len = 0; 343 q = buf+1; 344 pq = buf; 345 label_len = 0; 346 for (s = str; *s; s++, q++) { 347 if (q > buf + LDNS_MAX_DOMAINLEN) { 348 return LDNS_STATUS_DOMAINNAME_OVERFLOW; 349 } 350 *q = 0; 351 switch (*s) { 352 case '.': 353 if (label_len > LDNS_MAX_LABELLEN) { 354 return LDNS_STATUS_LABEL_OVERFLOW; 355 } 356 if (label_len == 0) { 357 return LDNS_STATUS_EMPTY_LABEL; 358 } 359 len += label_len + 1; 360 *pq = label_len; 361 label_len = 0; 362 pq = q; 363 break; 364 case '\\': 365 /* octet value or literal char */ 366 s += 1; 367 if (! parse_escape(q, &s)) { 368 return LDNS_STATUS_SYNTAX_BAD_ESCAPE; 369 } 370 s -= 1; 371 label_len++; 372 break; 373 default: 374 *q = (uint8_t)*s; 375 label_len++; 376 } 377 } 378 379 /* add root label if last char was not '.' */ 380 if (!ldns_dname_str_absolute(str)) { 381 if (q > buf + LDNS_MAX_DOMAINLEN) { 382 return LDNS_STATUS_DOMAINNAME_OVERFLOW; 383 } 384 if (label_len > LDNS_MAX_LABELLEN) { 385 return LDNS_STATUS_LABEL_OVERFLOW; 386 } 387 if (label_len == 0) { /* label_len 0 but not . at end? */ 388 return LDNS_STATUS_EMPTY_LABEL; 389 } 390 len += label_len + 1; 391 *pq = label_len; 392 *q = 0; 393 } 394 len++; 395 396 *d = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME, len, buf); 397 return LDNS_STATUS_OK; 398 } 399 400 ldns_status 401 ldns_str2rdf_a(ldns_rdf **rd, const char *str) 402 { 403 in_addr_t address; 404 if (inet_pton(AF_INET, (char*)str, &address) != 1) { 405 return LDNS_STATUS_INVALID_IP4; 406 } else { 407 *rd = ldns_rdf_new_frm_data( 408 LDNS_RDF_TYPE_A, sizeof(address), &address); 409 } 410 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 411 } 412 413 ldns_status 414 ldns_str2rdf_aaaa(ldns_rdf **rd, const char *str) 415 { 416 uint8_t address[LDNS_IP6ADDRLEN + 1]; 417 418 if (inet_pton(AF_INET6, (char*)str, address) != 1) { 419 return LDNS_STATUS_INVALID_IP6; 420 } else { 421 *rd = ldns_rdf_new_frm_data( 422 LDNS_RDF_TYPE_AAAA, sizeof(address) - 1, &address); 423 } 424 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 425 } 426 427 ldns_status 428 ldns_str2rdf_str(ldns_rdf **rd, const char *str) 429 { 430 uint8_t *data, *dp, ch = 0; 431 size_t length; 432 433 /* Worst case space requirement. We'll realloc to actual size later. */ 434 dp = data = LDNS_XMALLOC(uint8_t, strlen(str) > 255 ? 256 : (strlen(str) + 1)); 435 if (! data) { 436 return LDNS_STATUS_MEM_ERR; 437 } 438 439 /* Fill data (up to 255 characters) */ 440 while (parse_char(&ch, &str)) { 441 if (dp - data >= 255) { 442 LDNS_FREE(data); 443 return LDNS_STATUS_INVALID_STR; 444 } 445 *++dp = ch; 446 } 447 if (! str) { 448 return LDNS_STATUS_SYNTAX_BAD_ESCAPE; 449 } 450 length = (size_t)(dp - data); 451 /* Fix last length byte */ 452 data[0] = (uint8_t)length; 453 454 /* Lose the overmeasure */ 455 data = LDNS_XREALLOC(dp = data, uint8_t, length + 1); 456 if (! data) { 457 LDNS_FREE(dp); 458 return LDNS_STATUS_MEM_ERR; 459 } 460 461 /* Create rdf */ 462 *rd = ldns_rdf_new(LDNS_RDF_TYPE_STR, length + 1, data); 463 if (! *rd) { 464 LDNS_FREE(data); 465 return LDNS_STATUS_MEM_ERR; 466 } 467 return LDNS_STATUS_OK; 468 } 469 470 ldns_status 471 ldns_str2rdf_apl(ldns_rdf **rd, const char *str) 472 { 473 const char *my_str = str; 474 475 char *my_ip_str; 476 size_t ip_str_len; 477 478 uint16_t family; 479 bool negation; 480 uint8_t afdlength = 0; 481 uint8_t *afdpart; 482 uint8_t prefix; 483 484 uint8_t *data; 485 486 size_t i = 0; 487 488 /* [!]afi:address/prefix */ 489 if (strlen(my_str) < 2 490 || strchr(my_str, ':') == NULL 491 || strchr(my_str, '/') == NULL 492 || strchr(my_str, ':') > strchr(my_str, '/')) { 493 return LDNS_STATUS_INVALID_STR; 494 } 495 496 if (my_str[0] == '!') { 497 negation = true; 498 my_str += 1; 499 } else { 500 negation = false; 501 } 502 503 family = (uint16_t) atoi(my_str); 504 505 my_str = strchr(my_str, ':') + 1; 506 507 /* need ip addr and only ip addr for inet_pton */ 508 ip_str_len = (size_t) (strchr(my_str, '/') - my_str); 509 my_ip_str = LDNS_XMALLOC(char, ip_str_len + 1); 510 if(!my_ip_str) return LDNS_STATUS_MEM_ERR; 511 strncpy(my_ip_str, my_str, ip_str_len + 1); 512 my_ip_str[ip_str_len] = '\0'; 513 514 if (family == 1) { 515 /* ipv4 */ 516 afdpart = LDNS_XMALLOC(uint8_t, 4); 517 if(!afdpart) { 518 LDNS_FREE(my_ip_str); 519 return LDNS_STATUS_MEM_ERR; 520 } 521 if (inet_pton(AF_INET, my_ip_str, afdpart) == 0) { 522 LDNS_FREE(my_ip_str); 523 LDNS_FREE(afdpart); 524 return LDNS_STATUS_INVALID_STR; 525 } 526 for (i = 0; i < 4; i++) { 527 if (afdpart[i] != 0) { 528 afdlength = i + 1; 529 } 530 } 531 } else if (family == 2) { 532 /* ipv6 */ 533 afdpart = LDNS_XMALLOC(uint8_t, 16); 534 if(!afdpart) { 535 LDNS_FREE(my_ip_str); 536 return LDNS_STATUS_MEM_ERR; 537 } 538 if (inet_pton(AF_INET6, my_ip_str, afdpart) == 0) { 539 LDNS_FREE(my_ip_str); 540 LDNS_FREE(afdpart); 541 return LDNS_STATUS_INVALID_STR; 542 } 543 for (i = 0; i < 16; i++) { 544 if (afdpart[i] != 0) { 545 afdlength = i + 1; 546 } 547 } 548 } else { 549 /* unknown family */ 550 LDNS_FREE(my_ip_str); 551 return LDNS_STATUS_INVALID_STR; 552 } 553 554 my_str = strchr(my_str, '/') + 1; 555 prefix = (uint8_t) atoi(my_str); 556 557 data = LDNS_XMALLOC(uint8_t, 4 + afdlength); 558 if(!data) { 559 LDNS_FREE(afdpart); 560 LDNS_FREE(my_ip_str); 561 return LDNS_STATUS_INVALID_STR; 562 } 563 ldns_write_uint16(data, family); 564 data[2] = prefix; 565 data[3] = afdlength; 566 if (negation) { 567 /* set bit 1 of byte 3 */ 568 data[3] = data[3] | 0x80; 569 } 570 571 memcpy(data + 4, afdpart, afdlength); 572 573 *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_APL, afdlength + 4, data); 574 LDNS_FREE(afdpart); 575 LDNS_FREE(data); 576 LDNS_FREE(my_ip_str); 577 578 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 579 } 580 581 ldns_status 582 ldns_str2rdf_b64(ldns_rdf **rd, const char *str) 583 { 584 uint8_t *buffer; 585 int16_t i; 586 587 buffer = LDNS_XMALLOC(uint8_t, ldns_b64_ntop_calculate_size(strlen(str))); 588 if(!buffer) { 589 return LDNS_STATUS_MEM_ERR; 590 } 591 592 i = (uint16_t)ldns_b64_pton((const char*)str, buffer, 593 ldns_b64_ntop_calculate_size(strlen(str))); 594 if (-1 == i) { 595 LDNS_FREE(buffer); 596 return LDNS_STATUS_INVALID_B64; 597 } else { 598 *rd = ldns_rdf_new_frm_data( 599 LDNS_RDF_TYPE_B64, (uint16_t) i, buffer); 600 } 601 LDNS_FREE(buffer); 602 603 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 604 } 605 606 ldns_status 607 ldns_str2rdf_b32_ext(ldns_rdf **rd, const char *str) 608 { 609 uint8_t *buffer; 610 int i; 611 /* first byte contains length of actual b32 data */ 612 uint8_t len = ldns_b32_pton_calculate_size(strlen(str)); 613 buffer = LDNS_XMALLOC(uint8_t, len + 1); 614 if(!buffer) { 615 return LDNS_STATUS_MEM_ERR; 616 } 617 buffer[0] = len; 618 619 i = ldns_b32_pton_extended_hex((const char*)str, strlen(str), buffer + 1, 620 ldns_b32_ntop_calculate_size(strlen(str))); 621 if (i < 0) { 622 LDNS_FREE(buffer); 623 return LDNS_STATUS_INVALID_B32_EXT; 624 } else { 625 *rd = ldns_rdf_new_frm_data( 626 LDNS_RDF_TYPE_B32_EXT, (uint16_t) i + 1, buffer); 627 } 628 LDNS_FREE(buffer); 629 630 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 631 } 632 633 ldns_status 634 ldns_str2rdf_hex(ldns_rdf **rd, const char *str) 635 { 636 uint8_t *t, *t_orig; 637 int i; 638 size_t len; 639 640 len = strlen(str); 641 642 if (len > LDNS_MAX_RDFLEN * 2) { 643 return LDNS_STATUS_LABEL_OVERFLOW; 644 } else { 645 t = LDNS_XMALLOC(uint8_t, (len / 2) + 1); 646 if(!t) { 647 return LDNS_STATUS_MEM_ERR; 648 } 649 t_orig = t; 650 /* Now process octet by octet... */ 651 while (*str) { 652 *t = 0; 653 if (isspace((int) *str)) { 654 str++; 655 } else { 656 for (i = 16; i >= 1; i -= 15) { 657 while (*str && isspace((int) *str)) { str++; } 658 if (*str) { 659 if (isxdigit((int) *str)) { 660 *t += ldns_hexdigit_to_int(*str) * i; 661 } else { 662 LDNS_FREE(t_orig); 663 return LDNS_STATUS_ERR; 664 } 665 ++str; 666 } 667 } 668 ++t; 669 } 670 } 671 *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_HEX, 672 (size_t) (t - t_orig), 673 t_orig); 674 LDNS_FREE(t_orig); 675 } 676 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 677 } 678 679 ldns_status 680 ldns_str2rdf_nsec(ldns_rdf **rd, const char *str) 681 { 682 const char *delimiters = "\n\t "; 683 char *token = LDNS_XMALLOC(char, LDNS_MAX_RDFLEN); 684 ldns_buffer *str_buf; 685 ssize_t c; 686 uint16_t cur_type; 687 size_t type_count = 0; 688 ldns_rr_type type_list[65536]; 689 if(!token) return LDNS_STATUS_MEM_ERR; 690 if(rd == NULL) { 691 LDNS_FREE(token); 692 return LDNS_STATUS_NULL; 693 } 694 695 str_buf = LDNS_MALLOC(ldns_buffer); 696 if(!str_buf) { 697 LDNS_FREE(token); 698 return LDNS_STATUS_MEM_ERR; 699 } 700 ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str)); 701 if(ldns_buffer_status(str_buf) != LDNS_STATUS_OK) { 702 LDNS_FREE(str_buf); 703 LDNS_FREE(token); 704 return LDNS_STATUS_MEM_ERR; 705 } 706 707 while ((c = ldns_bget_token(str_buf, token, delimiters, LDNS_MAX_RDFLEN)) != -1 && c != 0) { 708 if(type_count >= sizeof(type_list)) { 709 LDNS_FREE(str_buf); 710 LDNS_FREE(token); 711 return LDNS_STATUS_ERR; 712 } 713 cur_type = ldns_get_rr_type_by_name(token); 714 type_list[type_count] = cur_type; 715 type_count++; 716 } 717 718 *rd = ldns_dnssec_create_nsec_bitmap(type_list, 719 type_count, 720 LDNS_RR_TYPE_NSEC); 721 722 LDNS_FREE(token); 723 ldns_buffer_free(str_buf); 724 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 725 } 726 727 ldns_status 728 ldns_str2rdf_type(ldns_rdf **rd, const char *str) 729 { 730 uint16_t type; 731 type = htons(ldns_get_rr_type_by_name(str)); 732 /* ldns_rr_type is a 16 bit value */ 733 *rd = ldns_rdf_new_frm_data( 734 LDNS_RDF_TYPE_TYPE, sizeof(uint16_t), &type); 735 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 736 } 737 738 ldns_status 739 ldns_str2rdf_class(ldns_rdf **rd, const char *str) 740 { 741 uint16_t klass; 742 klass = htons(ldns_get_rr_class_by_name(str)); 743 /* class is 16 bit */ 744 *rd = ldns_rdf_new_frm_data( 745 LDNS_RDF_TYPE_CLASS, sizeof(uint16_t), &klass); 746 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 747 } 748 749 /* An certificate alg field can either be specified as a 8 bits number 750 * or by its symbolic name. Handle both 751 */ 752 ldns_status 753 ldns_str2rdf_cert_alg(ldns_rdf **rd, const char *str) 754 { 755 ldns_lookup_table *lt; 756 ldns_status st; 757 uint8_t idd[2]; 758 lt = ldns_lookup_by_name(ldns_cert_algorithms, str); 759 st = LDNS_STATUS_OK; 760 761 if (lt) { 762 ldns_write_uint16(idd, (uint16_t) lt->id); 763 *rd = ldns_rdf_new_frm_data( 764 LDNS_RDF_TYPE_INT16, sizeof(uint16_t), idd); 765 if (!*rd) { 766 st = LDNS_STATUS_ERR; 767 } 768 } else { 769 /* try as-is (a number) */ 770 st = ldns_str2rdf_int16(rd, str); 771 if (st == LDNS_STATUS_OK && 772 ldns_rdf2native_int16(*rd) == 0) { 773 st = LDNS_STATUS_CERT_BAD_ALGORITHM; 774 } 775 } 776 777 return st; 778 } 779 780 static ldns_lookup_table ldns_tlsa_certificate_usages[] = { 781 { LDNS_TLSA_USAGE_PKIX_TA , "PKIX-TA" }, 782 { LDNS_TLSA_USAGE_PKIX_EE , "PKIX-EE" }, 783 { LDNS_TLSA_USAGE_DANE_TA , "DANE-TA" }, 784 { LDNS_TLSA_USAGE_DANE_EE , "DANE-EE" }, 785 { LDNS_TLSA_USAGE_PRIVCERT , "PrivCert" }, 786 { 0, NULL } 787 }; 788 789 static ldns_lookup_table ldns_tlsa_selectors[] = { 790 { LDNS_TLSA_SELECTOR_CERT , "Cert" }, 791 { LDNS_TLSA_SELECTOR_SPKI , "SPKI" }, 792 { LDNS_TLSA_SELECTOR_PRIVSEL , "PrivSel" }, 793 { 0, NULL } 794 }; 795 796 static ldns_lookup_table ldns_tlsa_matching_types[] = { 797 { LDNS_TLSA_MATCHING_TYPE_FULL , "Full" }, 798 { LDNS_TLSA_MATCHING_TYPE_SHA2_256 , "SHA2-256" }, 799 { LDNS_TLSA_MATCHING_TYPE_SHA2_512 , "SHA2-512" }, 800 { LDNS_TLSA_MATCHING_TYPE_PRIVMATCH , "PrivMatch" }, 801 { 0, NULL } 802 }; 803 804 static ldns_status 805 ldns_str2rdf_mnemonic4int8(ldns_lookup_table *lt, 806 ldns_rdf **rd, const char *str) 807 { 808 if ((lt = ldns_lookup_by_name(lt, str))) { 809 /* it was given as a integer */ 810 *rd = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, (uint8_t) lt->id); 811 if (!*rd) 812 return LDNS_STATUS_ERR; 813 else 814 return LDNS_STATUS_OK; 815 } 816 return ldns_str2rdf_int8(rd, str); 817 } 818 819 /* An alg field can either be specified as a 8 bits number 820 * or by its symbolic name. Handle both 821 */ 822 ldns_status 823 ldns_str2rdf_alg(ldns_rdf **rd, const char *str) 824 { 825 return ldns_str2rdf_mnemonic4int8(ldns_algorithms, rd, str); 826 } 827 828 ldns_status 829 ldns_str2rdf_certificate_usage(ldns_rdf **rd, const char *str) 830 { 831 return ldns_str2rdf_mnemonic4int8( 832 ldns_tlsa_certificate_usages, rd, str); 833 } 834 835 ldns_status 836 ldns_str2rdf_selector(ldns_rdf **rd, const char *str) 837 { 838 return ldns_str2rdf_mnemonic4int8(ldns_tlsa_selectors, rd, str); 839 } 840 841 ldns_status 842 ldns_str2rdf_matching_type(ldns_rdf **rd, const char *str) 843 { 844 return ldns_str2rdf_mnemonic4int8(ldns_tlsa_matching_types, rd, str); 845 } 846 847 ldns_status 848 ldns_str2rdf_unknown( ATTR_UNUSED(ldns_rdf **rd) 849 , ATTR_UNUSED(const char *str) 850 ) 851 { 852 /* this should be caught in an earlier time (general str2host for 853 rr's */ 854 return LDNS_STATUS_NOT_IMPL; 855 } 856 857 ldns_status 858 ldns_str2rdf_service( ATTR_UNUSED(ldns_rdf **rd) 859 , ATTR_UNUSED(const char *str) 860 ) 861 { 862 /* is this used? is this actually WKS? or SRV? */ 863 return LDNS_STATUS_NOT_IMPL; 864 } 865 866 static int 867 loc_parse_cm(char* my_str, char** endstr, uint8_t* m, uint8_t* e) 868 { 869 /* read <digits>[.<digits>][mM] */ 870 /* into mantissa exponent format for LOC type */ 871 uint32_t meters = 0, cm = 0, val; 872 while (isblank((unsigned char)*my_str)) { 873 my_str++; 874 } 875 meters = (uint32_t)strtol(my_str, &my_str, 10); 876 if (*my_str == '.') { 877 my_str++; 878 cm = (uint32_t)strtol(my_str, &my_str, 10); 879 } 880 if (meters >= 1) { 881 *e = 2; 882 val = meters; 883 } else { 884 *e = 0; 885 val = cm; 886 } 887 while(val >= 10) { 888 (*e)++; 889 val /= 10; 890 } 891 *m = (uint8_t)val; 892 893 if (*e > 9) 894 return 0; 895 if (*my_str == 'm' || *my_str == 'M') { 896 my_str++; 897 } 898 *endstr = my_str; 899 return 1; 900 } 901 902 ldns_status 903 ldns_str2rdf_loc(ldns_rdf **rd, const char *str) 904 { 905 uint32_t latitude = 0; 906 uint32_t longitude = 0; 907 uint32_t altitude = 0; 908 909 uint8_t *data; 910 uint32_t equator = (uint32_t) ldns_power(2, 31); 911 912 uint32_t h = 0; 913 uint32_t m = 0; 914 uint8_t size_b = 1, size_e = 2; 915 uint8_t horiz_pre_b = 1, horiz_pre_e = 6; 916 uint8_t vert_pre_b = 1, vert_pre_e = 3; 917 918 double s = 0.0; 919 bool northerness; 920 bool easterness; 921 922 char *my_str = (char *) str; 923 924 /* only support version 0 */ 925 if (isdigit((int) *my_str)) { 926 h = (uint32_t) strtol(my_str, &my_str, 10); 927 } else { 928 return LDNS_STATUS_INVALID_STR; 929 } 930 931 while (isblank((int) *my_str)) { 932 my_str++; 933 } 934 935 if (isdigit((int) *my_str)) { 936 m = (uint32_t) strtol(my_str, &my_str, 10); 937 } else if (*my_str == 'N' || *my_str == 'S') { 938 goto north; 939 } else { 940 return LDNS_STATUS_INVALID_STR; 941 } 942 943 while (isblank((int) *my_str)) { 944 my_str++; 945 } 946 947 if (isdigit((int) *my_str)) { 948 s = strtod(my_str, &my_str); 949 } 950 north: 951 while (isblank((int) *my_str)) { 952 my_str++; 953 } 954 955 if (*my_str == 'N') { 956 northerness = true; 957 } else if (*my_str == 'S') { 958 northerness = false; 959 } else { 960 return LDNS_STATUS_INVALID_STR; 961 } 962 963 my_str++; 964 965 /* store number */ 966 s = 1000.0 * s; 967 /* add a little to make floor in conversion a round */ 968 s += 0.0005; 969 latitude = (uint32_t) s; 970 latitude += 1000 * 60 * m; 971 latitude += 1000 * 60 * 60 * h; 972 if (northerness) { 973 latitude = equator + latitude; 974 } else { 975 latitude = equator - latitude; 976 } 977 while (isblank((unsigned char)*my_str)) { 978 my_str++; 979 } 980 981 if (isdigit((int) *my_str)) { 982 h = (uint32_t) strtol(my_str, &my_str, 10); 983 } else { 984 return LDNS_STATUS_INVALID_STR; 985 } 986 987 while (isblank((int) *my_str)) { 988 my_str++; 989 } 990 991 if (isdigit((int) *my_str)) { 992 m = (uint32_t) strtol(my_str, &my_str, 10); 993 } else if (*my_str == 'E' || *my_str == 'W') { 994 goto east; 995 } else { 996 return LDNS_STATUS_INVALID_STR; 997 } 998 999 while (isblank((unsigned char)*my_str)) { 1000 my_str++; 1001 } 1002 1003 if (isdigit((int) *my_str)) { 1004 s = strtod(my_str, &my_str); 1005 } 1006 1007 east: 1008 while (isblank((unsigned char)*my_str)) { 1009 my_str++; 1010 } 1011 1012 if (*my_str == 'E') { 1013 easterness = true; 1014 } else if (*my_str == 'W') { 1015 easterness = false; 1016 } else { 1017 return LDNS_STATUS_INVALID_STR; 1018 } 1019 1020 my_str++; 1021 1022 /* store number */ 1023 s *= 1000.0; 1024 /* add a little to make floor in conversion a round */ 1025 s += 0.0005; 1026 longitude = (uint32_t) s; 1027 longitude += 1000 * 60 * m; 1028 longitude += 1000 * 60 * 60 * h; 1029 1030 if (easterness) { 1031 longitude += equator; 1032 } else { 1033 longitude = equator - longitude; 1034 } 1035 1036 altitude = (uint32_t)(strtod(my_str, &my_str)*100.0 + 1037 10000000.0 + 0.5); 1038 if (*my_str == 'm' || *my_str == 'M') { 1039 my_str++; 1040 } 1041 1042 if (strlen(my_str) > 0) { 1043 if(!loc_parse_cm(my_str, &my_str, &size_b, &size_e)) 1044 return LDNS_STATUS_INVALID_STR; 1045 } 1046 1047 if (strlen(my_str) > 0) { 1048 if(!loc_parse_cm(my_str, &my_str, &horiz_pre_b, &horiz_pre_e)) 1049 return LDNS_STATUS_INVALID_STR; 1050 } 1051 1052 if (strlen(my_str) > 0) { 1053 if(!loc_parse_cm(my_str, &my_str, &vert_pre_b, &vert_pre_e)) 1054 return LDNS_STATUS_INVALID_STR; 1055 } 1056 1057 data = LDNS_XMALLOC(uint8_t, 16); 1058 if(!data) { 1059 return LDNS_STATUS_MEM_ERR; 1060 } 1061 data[0] = 0; 1062 data[1] = 0; 1063 data[1] = ((size_b << 4) & 0xf0) | (size_e & 0x0f); 1064 data[2] = ((horiz_pre_b << 4) & 0xf0) | (horiz_pre_e & 0x0f); 1065 data[3] = ((vert_pre_b << 4) & 0xf0) | (vert_pre_e & 0x0f); 1066 ldns_write_uint32(data + 4, latitude); 1067 ldns_write_uint32(data + 8, longitude); 1068 ldns_write_uint32(data + 12, altitude); 1069 1070 *rd = ldns_rdf_new_frm_data( 1071 LDNS_RDF_TYPE_LOC, 16, data); 1072 1073 LDNS_FREE(data); 1074 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 1075 } 1076 1077 ldns_status 1078 ldns_str2rdf_wks(ldns_rdf **rd, const char *str) 1079 { 1080 uint8_t *bitmap = NULL; 1081 uint8_t *data; 1082 int bm_len = 0; 1083 1084 struct protoent *proto = NULL; 1085 struct servent *serv = NULL; 1086 int serv_port; 1087 1088 ldns_buffer *str_buf; 1089 1090 char *proto_str = NULL; 1091 char *token; 1092 if(strlen(str) == 0) 1093 token = LDNS_XMALLOC(char, 50); 1094 else token = LDNS_XMALLOC(char, strlen(str)+2); 1095 if(!token) return LDNS_STATUS_MEM_ERR; 1096 1097 str_buf = LDNS_MALLOC(ldns_buffer); 1098 if(!str_buf) {LDNS_FREE(token); return LDNS_STATUS_MEM_ERR;} 1099 ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str)); 1100 if(ldns_buffer_status(str_buf) != LDNS_STATUS_OK) { 1101 LDNS_FREE(str_buf); 1102 LDNS_FREE(token); 1103 return LDNS_STATUS_MEM_ERR; 1104 } 1105 1106 while(ldns_bget_token(str_buf, token, "\t\n ", strlen(str)) > 0) { 1107 if (!proto_str) { 1108 proto_str = strdup(token); 1109 if (!proto_str) { 1110 LDNS_FREE(bitmap); 1111 LDNS_FREE(token); 1112 ldns_buffer_free(str_buf); 1113 return LDNS_STATUS_INVALID_STR; 1114 } 1115 } else { 1116 serv = getservbyname(token, proto_str); 1117 if (serv) { 1118 serv_port = (int) ntohs((uint16_t) serv->s_port); 1119 } else { 1120 serv_port = atoi(token); 1121 } 1122 if (serv_port / 8 >= bm_len) { 1123 uint8_t *b2 = LDNS_XREALLOC(bitmap, uint8_t, (serv_port / 8) + 1); 1124 if(!b2) { 1125 LDNS_FREE(bitmap); 1126 LDNS_FREE(token); 1127 ldns_buffer_free(str_buf); 1128 free(proto_str); 1129 return LDNS_STATUS_INVALID_STR; 1130 } 1131 bitmap = b2; 1132 /* set to zero to be sure */ 1133 for (; bm_len <= serv_port / 8; bm_len++) { 1134 bitmap[bm_len] = 0; 1135 } 1136 } 1137 ldns_set_bit(bitmap + (serv_port / 8), 7 - (serv_port % 8), true); 1138 } 1139 } 1140 1141 if (!proto_str || !bitmap) { 1142 LDNS_FREE(bitmap); 1143 LDNS_FREE(token); 1144 ldns_buffer_free(str_buf); 1145 free(proto_str); 1146 return LDNS_STATUS_INVALID_STR; 1147 } 1148 1149 data = LDNS_XMALLOC(uint8_t, bm_len + 1); 1150 if(!data) { 1151 LDNS_FREE(token); 1152 ldns_buffer_free(str_buf); 1153 LDNS_FREE(bitmap); 1154 free(proto_str); 1155 return LDNS_STATUS_INVALID_STR; 1156 } 1157 if (proto_str) 1158 proto = getprotobyname(proto_str); 1159 if (proto) { 1160 data[0] = (uint8_t) proto->p_proto; 1161 } else if (proto_str) { 1162 data[0] = (uint8_t) atoi(proto_str); 1163 } 1164 memcpy(data + 1, bitmap, (size_t) bm_len); 1165 1166 *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_WKS, (uint16_t) (bm_len + 1), data); 1167 1168 LDNS_FREE(data); 1169 LDNS_FREE(token); 1170 ldns_buffer_free(str_buf); 1171 LDNS_FREE(bitmap); 1172 free(proto_str); 1173 #ifdef HAVE_ENDSERVENT 1174 endservent(); 1175 #endif 1176 #ifdef HAVE_ENDPROTOENT 1177 endprotoent(); 1178 #endif 1179 1180 if(!*rd) return LDNS_STATUS_MEM_ERR; 1181 1182 return LDNS_STATUS_OK; 1183 } 1184 1185 ldns_status 1186 ldns_str2rdf_nsap(ldns_rdf **rd, const char *str) 1187 { 1188 size_t len, i; 1189 char* nsap_str = (char*) str; 1190 1191 /* just a hex string with optional dots? */ 1192 if (str[0] != '0' || str[1] != 'x') { 1193 return LDNS_STATUS_INVALID_STR; 1194 } else { 1195 len = strlen(str); 1196 for (i=0; i < len; i++) { 1197 if (nsap_str[i] == '.') 1198 nsap_str[i] = ' '; 1199 } 1200 return ldns_str2rdf_hex(rd, str+2); 1201 } 1202 } 1203 1204 ldns_status 1205 ldns_str2rdf_atma(ldns_rdf **rd, const char *str) 1206 { 1207 size_t len, i; 1208 char* atma_str = (char*) str; 1209 ldns_status status; 1210 1211 /* just a hex string with optional dots? */ 1212 len = strlen(str); 1213 for (i=0; i < len; i++) { 1214 if (atma_str[i] == '.') 1215 atma_str[i] = ' '; 1216 } 1217 status = ldns_str2rdf_hex(rd, str); 1218 if (status != LDNS_STATUS_OK) { 1219 ; /* probably in e.164 format than */ 1220 } 1221 return status; 1222 } 1223 1224 ldns_status 1225 ldns_str2rdf_ipseckey(ldns_rdf **rd, const char *str) 1226 { 1227 uint8_t precedence = 0; 1228 uint8_t gateway_type = 0; 1229 uint8_t algorithm = 0; 1230 char* gateway = NULL; 1231 char* publickey = NULL; 1232 uint8_t *data; 1233 ldns_buffer *str_buf; 1234 char *token; 1235 int token_count = 0; 1236 int ipseckey_len = 0; 1237 ldns_rdf* gateway_rdf = NULL; 1238 ldns_rdf* publickey_rdf = NULL; 1239 ldns_status status = LDNS_STATUS_OK; 1240 1241 if(strlen(str) == 0) 1242 token = LDNS_XMALLOC(char, 256); 1243 else token = LDNS_XMALLOC(char, strlen(str)+2); 1244 if(!token) return LDNS_STATUS_MEM_ERR; 1245 1246 str_buf = LDNS_MALLOC(ldns_buffer); 1247 if(!str_buf) {LDNS_FREE(token); return LDNS_STATUS_MEM_ERR;} 1248 ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str)); 1249 if(ldns_buffer_status(str_buf) != LDNS_STATUS_OK) { 1250 LDNS_FREE(str_buf); 1251 LDNS_FREE(token); 1252 return LDNS_STATUS_MEM_ERR; 1253 } 1254 while(ldns_bget_token(str_buf, token, "\t\n ", strlen(str)) > 0) { 1255 switch (token_count) { 1256 case 0: 1257 precedence = (uint8_t)atoi(token); 1258 break; 1259 case 1: 1260 gateway_type = (uint8_t)atoi(token); 1261 break; 1262 case 2: 1263 algorithm = (uint8_t)atoi(token); 1264 break; 1265 case 3: 1266 gateway = strdup(token); 1267 if (!gateway || (gateway_type == 0 && 1268 (token[0] != '.' || token[1] != '\0'))) { 1269 LDNS_FREE(gateway); 1270 LDNS_FREE(token); 1271 ldns_buffer_free(str_buf); 1272 return LDNS_STATUS_INVALID_STR; 1273 } 1274 break; 1275 case 4: 1276 publickey = strdup(token); 1277 break; 1278 default: 1279 LDNS_FREE(token); 1280 ldns_buffer_free(str_buf); 1281 return LDNS_STATUS_INVALID_STR; 1282 break; 1283 } 1284 token_count++; 1285 } 1286 1287 if (!gateway || !publickey) { 1288 if (gateway) 1289 LDNS_FREE(gateway); 1290 if (publickey) 1291 LDNS_FREE(publickey); 1292 LDNS_FREE(token); 1293 ldns_buffer_free(str_buf); 1294 return LDNS_STATUS_INVALID_STR; 1295 } 1296 1297 if (gateway_type == 1) { 1298 status = ldns_str2rdf_a(&gateway_rdf, gateway); 1299 } else if (gateway_type == 2) { 1300 status = ldns_str2rdf_aaaa(&gateway_rdf, gateway); 1301 } else if (gateway_type == 3) { 1302 status = ldns_str2rdf_dname(&gateway_rdf, gateway); 1303 } 1304 1305 if (status != LDNS_STATUS_OK) { 1306 if (gateway) 1307 LDNS_FREE(gateway); 1308 if (publickey) 1309 LDNS_FREE(publickey); 1310 LDNS_FREE(token); 1311 ldns_buffer_free(str_buf); 1312 return LDNS_STATUS_INVALID_STR; 1313 } 1314 1315 status = ldns_str2rdf_b64(&publickey_rdf, publickey); 1316 1317 if (status != LDNS_STATUS_OK) { 1318 if (gateway) 1319 LDNS_FREE(gateway); 1320 if (publickey) 1321 LDNS_FREE(publickey); 1322 LDNS_FREE(token); 1323 ldns_buffer_free(str_buf); 1324 if (gateway_rdf) ldns_rdf_free(gateway_rdf); 1325 return LDNS_STATUS_INVALID_STR; 1326 } 1327 1328 /* now copy all into one ipseckey rdf */ 1329 if (gateway_type) 1330 ipseckey_len = 3 + (int)ldns_rdf_size(gateway_rdf) + (int)ldns_rdf_size(publickey_rdf); 1331 else 1332 ipseckey_len = 3 + (int)ldns_rdf_size(publickey_rdf); 1333 1334 data = LDNS_XMALLOC(uint8_t, ipseckey_len); 1335 if(!data) { 1336 if (gateway) 1337 LDNS_FREE(gateway); 1338 if (publickey) 1339 LDNS_FREE(publickey); 1340 LDNS_FREE(token); 1341 ldns_buffer_free(str_buf); 1342 if (gateway_rdf) ldns_rdf_free(gateway_rdf); 1343 if (publickey_rdf) ldns_rdf_free(publickey_rdf); 1344 return LDNS_STATUS_MEM_ERR; 1345 } 1346 1347 data[0] = precedence; 1348 data[1] = gateway_type; 1349 data[2] = algorithm; 1350 1351 if (gateway_type) { 1352 memcpy(data + 3, 1353 ldns_rdf_data(gateway_rdf), ldns_rdf_size(gateway_rdf)); 1354 memcpy(data + 3 + ldns_rdf_size(gateway_rdf), 1355 ldns_rdf_data(publickey_rdf), ldns_rdf_size(publickey_rdf)); 1356 } else { 1357 memcpy(data + 3, 1358 ldns_rdf_data(publickey_rdf), ldns_rdf_size(publickey_rdf)); 1359 } 1360 1361 *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_IPSECKEY, (uint16_t) ipseckey_len, data); 1362 1363 if (gateway) 1364 LDNS_FREE(gateway); 1365 if (publickey) 1366 LDNS_FREE(publickey); 1367 LDNS_FREE(token); 1368 ldns_buffer_free(str_buf); 1369 ldns_rdf_free(gateway_rdf); 1370 ldns_rdf_free(publickey_rdf); 1371 LDNS_FREE(data); 1372 if(!*rd) return LDNS_STATUS_MEM_ERR; 1373 return LDNS_STATUS_OK; 1374 } 1375 1376 ldns_status 1377 ldns_str2rdf_ilnp64(ldns_rdf **rd, const char *str) 1378 { 1379 unsigned int a, b, c, d; 1380 uint16_t shorts[4]; 1381 int l; 1382 1383 if (sscanf(str, "%4x:%4x:%4x:%4x%n", &a, &b, &c, &d, &l) != 4 || 1384 l != (int)strlen(str) || /* more data to read */ 1385 strpbrk(str, "+-") /* signed hexes */ 1386 ) { 1387 return LDNS_STATUS_INVALID_ILNP64; 1388 } else { 1389 shorts[0] = htons(a); 1390 shorts[1] = htons(b); 1391 shorts[2] = htons(c); 1392 shorts[3] = htons(d); 1393 *rd = ldns_rdf_new_frm_data( 1394 LDNS_RDF_TYPE_ILNP64, 4 * sizeof(uint16_t), &shorts); 1395 } 1396 return *rd ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR; 1397 } 1398 1399 ldns_status 1400 ldns_str2rdf_eui48(ldns_rdf **rd, const char *str) 1401 { 1402 unsigned int a, b, c, d, e, f; 1403 uint8_t bytes[6]; 1404 int l; 1405 1406 if (sscanf(str, "%2x-%2x-%2x-%2x-%2x-%2x%n", 1407 &a, &b, &c, &d, &e, &f, &l) != 6 || 1408 l != (int)strlen(str)) { 1409 return LDNS_STATUS_INVALID_EUI48; 1410 } else { 1411 bytes[0] = a; 1412 bytes[1] = b; 1413 bytes[2] = c; 1414 bytes[3] = d; 1415 bytes[4] = e; 1416 bytes[5] = f; 1417 *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_EUI48, 6, &bytes); 1418 } 1419 return *rd ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR; 1420 } 1421 1422 ldns_status 1423 ldns_str2rdf_eui64(ldns_rdf **rd, const char *str) 1424 { 1425 unsigned int a, b, c, d, e, f, g, h; 1426 uint8_t bytes[8]; 1427 int l; 1428 1429 if (sscanf(str, "%2x-%2x-%2x-%2x-%2x-%2x-%2x-%2x%n", 1430 &a, &b, &c, &d, &e, &f, &g, &h, &l) != 8 || 1431 l != (int)strlen(str)) { 1432 return LDNS_STATUS_INVALID_EUI64; 1433 } else { 1434 bytes[0] = a; 1435 bytes[1] = b; 1436 bytes[2] = c; 1437 bytes[3] = d; 1438 bytes[4] = e; 1439 bytes[5] = f; 1440 bytes[6] = g; 1441 bytes[7] = h; 1442 *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_EUI64, 8, &bytes); 1443 } 1444 return *rd ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR; 1445 } 1446 1447 ldns_status 1448 ldns_str2rdf_tag(ldns_rdf **rd, const char *str) 1449 { 1450 uint8_t *data; 1451 const char* ptr; 1452 1453 if (strlen(str) > 255) { 1454 return LDNS_STATUS_INVALID_TAG; 1455 } 1456 for (ptr = str; *ptr; ptr++) { 1457 if (! isalnum((unsigned char)*ptr)) { 1458 return LDNS_STATUS_INVALID_TAG; 1459 } 1460 } 1461 data = LDNS_XMALLOC(uint8_t, strlen(str) + 1); 1462 if (!data) { 1463 return LDNS_STATUS_MEM_ERR; 1464 } 1465 data[0] = strlen(str); 1466 memcpy(data + 1, str, strlen(str)); 1467 1468 *rd = ldns_rdf_new(LDNS_RDF_TYPE_TAG, strlen(str) + 1, data); 1469 if (!*rd) { 1470 LDNS_FREE(data); 1471 return LDNS_STATUS_MEM_ERR; 1472 } 1473 return LDNS_STATUS_OK; 1474 } 1475 1476 ldns_status 1477 ldns_str2rdf_long_str(ldns_rdf **rd, const char *str) 1478 { 1479 uint8_t *data, *dp, ch = 0; 1480 size_t length; 1481 1482 /* Worst case space requirement. We'll realloc to actual size later. */ 1483 dp = data = LDNS_XMALLOC(uint8_t, strlen(str)); 1484 if (! data) { 1485 return LDNS_STATUS_MEM_ERR; 1486 } 1487 1488 /* Fill data with parsed bytes */ 1489 while (parse_char(&ch, &str)) { 1490 *dp++ = ch; 1491 if (dp - data > LDNS_MAX_RDFLEN) { 1492 LDNS_FREE(data); 1493 return LDNS_STATUS_INVALID_STR; 1494 } 1495 } 1496 if (! str) { 1497 return LDNS_STATUS_SYNTAX_BAD_ESCAPE; 1498 } 1499 length = (size_t)(dp - data); 1500 1501 /* Lose the overmeasure */ 1502 data = LDNS_XREALLOC(dp = data, uint8_t, length); 1503 if (! data) { 1504 LDNS_FREE(dp); 1505 return LDNS_STATUS_MEM_ERR; 1506 } 1507 1508 /* Create rdf */ 1509 *rd = ldns_rdf_new(LDNS_RDF_TYPE_LONG_STR, length, data); 1510 if (! *rd) { 1511 LDNS_FREE(data); 1512 return LDNS_STATUS_MEM_ERR; 1513 } 1514 return LDNS_STATUS_OK; 1515 } 1516 1517 ldns_status 1518 ldns_str2rdf_hip(ldns_rdf **rd, const char *str) 1519 { 1520 const char *hit = strchr(str, ' ') + 1; 1521 const char *pk = hit == NULL ? NULL : strchr(hit, ' ') + 1; 1522 size_t hit_size = hit == NULL ? 0 1523 : pk == NULL ? strlen(hit) : (size_t) (pk - hit) - 1; 1524 size_t pk_size = pk == NULL ? 0 : strlen(pk); 1525 size_t hit_wire_size = (hit_size + 1) / 2; 1526 size_t pk_wire_size = ldns_b64_pton_calculate_size(pk_size); 1527 size_t rdf_size = 4 + hit_wire_size + pk_wire_size; 1528 1529 char *endptr; /* utility var for strtol usage */ 1530 int algorithm = strtol(str, &endptr, 10); 1531 1532 uint8_t *data, *dp; 1533 int hi, lo, written; 1534 1535 if (hit_size == 0 || pk_size == 0 || (hit_size + 1) / 2 > 255 1536 || rdf_size > LDNS_MAX_RDFLEN 1537 || algorithm < 0 || algorithm > 255 1538 || (errno != 0 && algorithm == 0) /* out of range */ 1539 || endptr == str /* no digits */) { 1540 1541 return LDNS_STATUS_SYNTAX_ERR; 1542 } 1543 if ((data = LDNS_XMALLOC(uint8_t, rdf_size)) == NULL) { 1544 1545 return LDNS_STATUS_MEM_ERR; 1546 } 1547 /* From RFC 5205 section 5. HIP RR Storage Format: 1548 ************************************************* 1549 1550 0 1 2 3 1551 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 1552 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1553 | HIT length | PK algorithm | PK length | 1554 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1555 | | 1556 ~ HIT ~ 1557 | | 1558 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1559 | | | 1560 +-+-+-+-+-+-+-+-+-+-+-+ + 1561 | Public Key | 1562 ~ ~ 1563 | | 1564 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1565 | | | 1566 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + 1567 | | 1568 ~ Rendezvous Servers ~ 1569 | | 1570 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1571 | | 1572 +-+-+-+-+-+-+-+ */ 1573 1574 data[0] = (uint8_t) hit_wire_size; 1575 data[1] = (uint8_t) algorithm; 1576 1577 for (dp = data + 4; *hit && *hit != ' '; dp++) { 1578 1579 if ((hi = ldns_hexdigit_to_int(*hit++)) == -1 || 1580 (lo = ldns_hexdigit_to_int(*hit++)) == -1) { 1581 1582 LDNS_FREE(data); 1583 return LDNS_STATUS_INVALID_HEX; 1584 } 1585 *dp = (uint8_t) hi << 4 | lo; 1586 } 1587 if ((written = ldns_b64_pton(pk, dp, pk_wire_size)) <= 0) { 1588 1589 LDNS_FREE(data); 1590 return LDNS_STATUS_INVALID_B64; 1591 } 1592 1593 /* Because ldns_b64_pton_calculate_size isn't always correct: 1594 * (we have to fix it at some point) 1595 */ 1596 pk_wire_size = (uint16_t) written; 1597 ldns_write_uint16(data + 2, pk_wire_size); 1598 rdf_size = 4 + hit_wire_size + pk_wire_size; 1599 1600 /* Create rdf */ 1601 if (! (*rd = ldns_rdf_new(LDNS_RDF_TYPE_HIP, rdf_size, data))) { 1602 1603 LDNS_FREE(data); 1604 return LDNS_STATUS_MEM_ERR; 1605 } 1606 return LDNS_STATUS_OK; 1607 } 1608