str2host.c revision 238104
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 35ldns_status 36ldns_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 56ldns_status 57ldns_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(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 125ldns_status 126ldns_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 177ldns_status 178ldns_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 196ldns_status 197ldns_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 227ldns_status 228ldns_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 octal 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 octals) 256 * 257 * Returns the number of bytes read from the escaped string, or 258 * 0 on error 259 */ 260static int 261parse_escape(uint8_t *s, uint8_t *q) { 262 uint16_t val; 263 if (strlen((char *)s) > 3 && 264 isdigit((int) s[1]) && 265 isdigit((int) s[2]) && 266 isdigit((int) s[3])) { 267 /* cast this so it fits */ 268 val = (uint16_t) ldns_hexdigit_to_int((char) s[1]) * 100 + 269 ldns_hexdigit_to_int((char) s[2]) * 10 + 270 ldns_hexdigit_to_int((char) s[3]); 271 if (val > 255) { 272 /* outside range */ 273 return 0; 274 } 275 *q = (uint8_t) val; 276 return 3; 277 } else { 278 s++; 279 if (*s == '\0' || isdigit((int) *s)) { 280 /* apparently the string terminator 281 * or a digit has been escaped... 282 */ 283 return 0; 284 } 285 *q = *s; 286 return 1; 287 } 288} 289 290/* 291 * No special care is taken, all dots are translated into 292 * label seperators. 293 * Could be made more efficient....we do 3 memcpy's in total... 294 */ 295ldns_status 296ldns_str2rdf_dname(ldns_rdf **d, const char *str) 297{ 298 size_t len; 299 300 int esc; 301 uint8_t *s, *q, *pq, label_len; 302 uint8_t buf[LDNS_MAX_DOMAINLEN + 1]; 303 *d = NULL; 304 305 len = strlen((char*)str); 306 /* octet representation can make strings a lot longer than actual length */ 307 if (len > LDNS_MAX_DOMAINLEN * 4) { 308 return LDNS_STATUS_DOMAINNAME_OVERFLOW; 309 } 310 if (0 == len) { 311 return LDNS_STATUS_DOMAINNAME_UNDERFLOW; 312 } 313 314 /* root label */ 315 if (1 == len && *str == '.') { 316 *d = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME, 1, "\0"); 317 return LDNS_STATUS_OK; 318 } 319 320 /* get on with the rest */ 321 322 /* s is on the current character in the string 323 * pq points to where the labellength is going to go 324 * label_len keeps track of the current label's length 325 * q builds the dname inside the buf array 326 */ 327 len = 0; 328 q = buf+1; 329 pq = buf; 330 label_len = 0; 331 for (s = (uint8_t *)str; *s; s++, q++) { 332 if (q > buf + LDNS_MAX_DOMAINLEN) { 333 return LDNS_STATUS_DOMAINNAME_OVERFLOW; 334 } 335 *q = 0; 336 switch (*s) { 337 case '.': 338 if (label_len > LDNS_MAX_LABELLEN) { 339 return LDNS_STATUS_LABEL_OVERFLOW; 340 } 341 if (label_len == 0) { 342 return LDNS_STATUS_EMPTY_LABEL; 343 } 344 len += label_len + 1; 345 *pq = label_len; 346 label_len = 0; 347 pq = q; 348 break; 349 case '\\': 350 /* octet value or literal char */ 351 esc = parse_escape(s, q); 352 if (esc > 0) { 353 s += esc; 354 label_len++; 355 } else { 356 return LDNS_STATUS_SYNTAX_BAD_ESCAPE; 357 } 358 break; 359 default: 360 *q = *s; 361 label_len++; 362 } 363 } 364 365 /* add root label if last char was not '.' */ 366 if (!ldns_dname_str_absolute(str)) { 367 if (q > buf + LDNS_MAX_DOMAINLEN) { 368 return LDNS_STATUS_DOMAINNAME_OVERFLOW; 369 } 370 if (label_len > LDNS_MAX_LABELLEN) { 371 return LDNS_STATUS_LABEL_OVERFLOW; 372 } 373 if (label_len == 0) { /* label_len 0 but not . at end? */ 374 return LDNS_STATUS_EMPTY_LABEL; 375 } 376 len += label_len + 1; 377 *pq = label_len; 378 *q = 0; 379 } 380 len++; 381 382 *d = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME, len, buf); 383 return LDNS_STATUS_OK; 384} 385 386ldns_status 387ldns_str2rdf_a(ldns_rdf **rd, const char *str) 388{ 389 in_addr_t address; 390 if (inet_pton(AF_INET, (char*)str, &address) != 1) { 391 return LDNS_STATUS_INVALID_IP4; 392 } else { 393 *rd = ldns_rdf_new_frm_data( 394 LDNS_RDF_TYPE_A, sizeof(address), &address); 395 } 396 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 397} 398 399ldns_status 400ldns_str2rdf_aaaa(ldns_rdf **rd, const char *str) 401{ 402 uint8_t address[LDNS_IP6ADDRLEN + 1]; 403 404 if (inet_pton(AF_INET6, (char*)str, address) != 1) { 405 return LDNS_STATUS_INVALID_IP6; 406 } else { 407 *rd = ldns_rdf_new_frm_data( 408 LDNS_RDF_TYPE_AAAA, sizeof(address) - 1, &address); 409 } 410 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 411} 412 413ldns_status 414ldns_str2rdf_str(ldns_rdf **rd, const char *str) 415{ 416 uint8_t *data; 417 size_t i, str_i, esc_i; 418 419 if (strlen(str) > 255) { 420 return LDNS_STATUS_INVALID_STR; 421 } 422 423 data = LDNS_XMALLOC(uint8_t, strlen(str) + 1); 424 if(!data) return LDNS_STATUS_MEM_ERR; 425 i = 1; 426 427 for (str_i = 0; str_i < strlen(str); str_i++) { 428 if (str[str_i] == '\\') { 429 /* octet value or literal char */ 430 esc_i = (size_t) parse_escape((uint8_t*) &str[str_i], (uint8_t*) &data[i]); 431 if (esc_i == 0) { 432 LDNS_FREE(data); 433 return LDNS_STATUS_SYNTAX_BAD_ESCAPE; 434 } 435 str_i += esc_i; 436 } else { 437 data[i] = (uint8_t) str[str_i]; 438 } 439 i++; 440 } 441 data[0] = i - 1; 442 *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_STR, i, data); 443 444 LDNS_FREE(data); 445 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 446} 447 448ldns_status 449ldns_str2rdf_apl(ldns_rdf **rd, const char *str) 450{ 451 const char *my_str = str; 452 453 char *my_ip_str; 454 size_t ip_str_len; 455 456 uint16_t family; 457 bool negation; 458 uint8_t afdlength = 0; 459 uint8_t *afdpart; 460 uint8_t prefix; 461 462 uint8_t *data; 463 464 size_t i = 0; 465 466 /* [!]afi:address/prefix */ 467 if (strlen(my_str) < 2 468 || strchr(my_str, ':') == NULL 469 || strchr(my_str, '/') == NULL 470 || strchr(my_str, ':') > strchr(my_str, '/')) { 471 return LDNS_STATUS_INVALID_STR; 472 } 473 474 if (my_str[0] == '!') { 475 negation = true; 476 my_str += 1; 477 } else { 478 negation = false; 479 } 480 481 family = (uint16_t) atoi(my_str); 482 483 my_str = strchr(my_str, ':') + 1; 484 485 /* need ip addr and only ip addr for inet_pton */ 486 ip_str_len = (size_t) (strchr(my_str, '/') - my_str); 487 my_ip_str = LDNS_XMALLOC(char, ip_str_len + 1); 488 if(!my_ip_str) return LDNS_STATUS_MEM_ERR; 489 strncpy(my_ip_str, my_str, ip_str_len + 1); 490 my_ip_str[ip_str_len] = '\0'; 491 492 if (family == 1) { 493 /* ipv4 */ 494 afdpart = LDNS_XMALLOC(uint8_t, 4); 495 if(!afdpart) { 496 LDNS_FREE(my_ip_str); 497 return LDNS_STATUS_MEM_ERR; 498 } 499 if (inet_pton(AF_INET, my_ip_str, afdpart) == 0) { 500 LDNS_FREE(my_ip_str); 501 LDNS_FREE(afdpart); 502 return LDNS_STATUS_INVALID_STR; 503 } 504 for (i = 0; i < 4; i++) { 505 if (afdpart[i] != 0) { 506 afdlength = i + 1; 507 } 508 } 509 } else if (family == 2) { 510 /* ipv6 */ 511 afdpart = LDNS_XMALLOC(uint8_t, 16); 512 if(!afdpart) { 513 LDNS_FREE(my_ip_str); 514 return LDNS_STATUS_MEM_ERR; 515 } 516 if (inet_pton(AF_INET6, my_ip_str, afdpart) == 0) { 517 LDNS_FREE(my_ip_str); 518 LDNS_FREE(afdpart); 519 return LDNS_STATUS_INVALID_STR; 520 } 521 for (i = 0; i < 16; i++) { 522 if (afdpart[i] != 0) { 523 afdlength = i + 1; 524 } 525 } 526 } else { 527 /* unknown family */ 528 LDNS_FREE(my_ip_str); 529 return LDNS_STATUS_INVALID_STR; 530 } 531 532 my_str = strchr(my_str, '/') + 1; 533 prefix = (uint8_t) atoi(my_str); 534 535 data = LDNS_XMALLOC(uint8_t, 4 + afdlength); 536 if(!data) { 537 LDNS_FREE(my_ip_str); 538 return LDNS_STATUS_INVALID_STR; 539 } 540 ldns_write_uint16(data, family); 541 data[2] = prefix; 542 data[3] = afdlength; 543 if (negation) { 544 /* set bit 1 of byte 3 */ 545 data[3] = data[3] | 0x80; 546 } 547 548 memcpy(data + 4, afdpart, afdlength); 549 550 *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_APL, afdlength + 4, data); 551 LDNS_FREE(afdpart); 552 LDNS_FREE(data); 553 LDNS_FREE(my_ip_str); 554 555 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 556} 557 558ldns_status 559ldns_str2rdf_b64(ldns_rdf **rd, const char *str) 560{ 561 uint8_t *buffer; 562 int16_t i; 563 564 buffer = LDNS_XMALLOC(uint8_t, ldns_b64_ntop_calculate_size(strlen(str))); 565 if(!buffer) { 566 return LDNS_STATUS_MEM_ERR; 567 } 568 569 i = (uint16_t)ldns_b64_pton((const char*)str, buffer, 570 ldns_b64_ntop_calculate_size(strlen(str))); 571 if (-1 == i) { 572 LDNS_FREE(buffer); 573 return LDNS_STATUS_INVALID_B64; 574 } else { 575 *rd = ldns_rdf_new_frm_data( 576 LDNS_RDF_TYPE_B64, (uint16_t) i, buffer); 577 } 578 LDNS_FREE(buffer); 579 580 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 581} 582 583ldns_status 584ldns_str2rdf_b32_ext(ldns_rdf **rd, const char *str) 585{ 586 uint8_t *buffer; 587 int i; 588 /* first byte contains length of actual b32 data */ 589 uint8_t len = ldns_b32_pton_calculate_size(strlen(str)); 590 buffer = LDNS_XMALLOC(uint8_t, len + 1); 591 if(!buffer) { 592 return LDNS_STATUS_MEM_ERR; 593 } 594 buffer[0] = len; 595 596 i = ldns_b32_pton_extended_hex((const char*)str, strlen(str), buffer + 1, 597 ldns_b32_ntop_calculate_size(strlen(str))); 598 if (i < 0) { 599 LDNS_FREE(buffer); 600 return LDNS_STATUS_INVALID_B32_EXT; 601 } else { 602 *rd = ldns_rdf_new_frm_data( 603 LDNS_RDF_TYPE_B32_EXT, (uint16_t) i + 1, buffer); 604 } 605 LDNS_FREE(buffer); 606 607 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 608} 609 610ldns_status 611ldns_str2rdf_hex(ldns_rdf **rd, const char *str) 612{ 613 uint8_t *t, *t_orig; 614 int i; 615 size_t len; 616 617 len = strlen(str); 618 619 if (len > LDNS_MAX_RDFLEN * 2) { 620 return LDNS_STATUS_LABEL_OVERFLOW; 621 } else { 622 t = LDNS_XMALLOC(uint8_t, (len / 2) + 1); 623 if(!t) { 624 return LDNS_STATUS_MEM_ERR; 625 } 626 t_orig = t; 627 /* Now process octet by octet... */ 628 while (*str) { 629 *t = 0; 630 if (isspace((int) *str)) { 631 str++; 632 } else { 633 for (i = 16; i >= 1; i -= 15) { 634 while (*str && isspace((int) *str)) { str++; } 635 if (*str) { 636 if (isxdigit((int) *str)) { 637 *t += ldns_hexdigit_to_int(*str) * i; 638 } else { 639 LDNS_FREE(t_orig); 640 return LDNS_STATUS_ERR; 641 } 642 ++str; 643 } 644 } 645 ++t; 646 } 647 } 648 *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_HEX, 649 (size_t) (t - t_orig), 650 t_orig); 651 LDNS_FREE(t_orig); 652 } 653 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 654} 655 656ldns_status 657ldns_str2rdf_nsec(ldns_rdf **rd, const char *str) 658{ 659 const char *delimiters = "\n\t "; 660 char *token = LDNS_XMALLOC(char, LDNS_MAX_RDFLEN); 661 ldns_buffer *str_buf; 662 ssize_t c; 663 uint16_t cur_type; 664 size_t type_count = 0; 665 ldns_rr_type type_list[65536]; 666 if(!token) return LDNS_STATUS_MEM_ERR; 667 if(rd == NULL) { 668 LDNS_FREE(token); 669 return LDNS_STATUS_NULL; 670 } 671 672 str_buf = LDNS_MALLOC(ldns_buffer); 673 if(!str_buf) { 674 LDNS_FREE(token); 675 return LDNS_STATUS_MEM_ERR; 676 } 677 ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str)); 678 if(ldns_buffer_status(str_buf) != LDNS_STATUS_OK) { 679 LDNS_FREE(str_buf); 680 LDNS_FREE(token); 681 return LDNS_STATUS_MEM_ERR; 682 } 683 684 while ((c = ldns_bget_token(str_buf, token, delimiters, LDNS_MAX_RDFLEN)) != -1 && c != 0) { 685 if(type_count >= sizeof(type_list)) { 686 LDNS_FREE(str_buf); 687 LDNS_FREE(token); 688 return LDNS_STATUS_ERR; 689 } 690 cur_type = ldns_get_rr_type_by_name(token); 691 type_list[type_count] = cur_type; 692 type_count++; 693 } 694 695 *rd = ldns_dnssec_create_nsec_bitmap(type_list, 696 type_count, 697 LDNS_RR_TYPE_NSEC); 698 699 LDNS_FREE(token); 700 ldns_buffer_free(str_buf); 701 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 702} 703 704ldns_status 705ldns_str2rdf_type(ldns_rdf **rd, const char *str) 706{ 707 uint16_t type; 708 type = htons(ldns_get_rr_type_by_name(str)); 709 /* ldns_rr_type is a 16 bit value */ 710 *rd = ldns_rdf_new_frm_data( 711 LDNS_RDF_TYPE_TYPE, sizeof(uint16_t), &type); 712 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 713} 714 715ldns_status 716ldns_str2rdf_class(ldns_rdf **rd, const char *str) 717{ 718 uint16_t klass; 719 klass = htons(ldns_get_rr_class_by_name(str)); 720 /* class is 16 bit */ 721 *rd = ldns_rdf_new_frm_data( 722 LDNS_RDF_TYPE_CLASS, sizeof(uint16_t), &klass); 723 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 724} 725 726/* An certificate alg field can either be specified as a 8 bits number 727 * or by its symbolic name. Handle both 728 */ 729ldns_status 730ldns_str2rdf_cert_alg(ldns_rdf **rd, const char *str) 731{ 732 ldns_lookup_table *lt; 733 ldns_status st; 734 uint8_t idd[2]; 735 lt = ldns_lookup_by_name(ldns_cert_algorithms, str); 736 st = LDNS_STATUS_OK; 737 738 if (lt) { 739 ldns_write_uint16(idd, (uint16_t) lt->id); 740 *rd = ldns_rdf_new_frm_data( 741 LDNS_RDF_TYPE_INT16, sizeof(uint16_t), idd); 742 if (!*rd) { 743 st = LDNS_STATUS_ERR; 744 } 745 } else { 746 /* try as-is (a number) */ 747 st = ldns_str2rdf_int16(rd, str); 748 if (st == LDNS_STATUS_OK && 749 ldns_rdf2native_int16(*rd) == 0) { 750 st = LDNS_STATUS_CERT_BAD_ALGORITHM; 751 } 752 } 753 754 return st; 755} 756 757/* An alg field can either be specified as a 8 bits number 758 * or by its symbolic name. Handle both 759 */ 760ldns_status 761ldns_str2rdf_alg(ldns_rdf **rd, const char *str) 762{ 763 ldns_lookup_table *lt; 764 ldns_status st; 765 766 lt = ldns_lookup_by_name(ldns_algorithms, str); 767 st = LDNS_STATUS_OK; 768 769 if (lt) { 770 /* it was given as a integer */ 771 *rd = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, (uint8_t) lt->id); 772 if (!*rd) { 773 st = LDNS_STATUS_ERR; 774 } 775 } else { 776 /* try as-is (a number) */ 777 st = ldns_str2rdf_int8(rd, str); 778 } 779 return st; 780} 781 782ldns_status 783ldns_str2rdf_unknown( ATTR_UNUSED(ldns_rdf **rd) 784 , ATTR_UNUSED(const char *str) 785 ) 786{ 787 /* this should be caught in an earlier time (general str2host for 788 rr's */ 789 return LDNS_STATUS_NOT_IMPL; 790} 791 792ldns_status 793ldns_str2rdf_tsig( ATTR_UNUSED(ldns_rdf **rd) 794 , ATTR_UNUSED(const char *str) 795 ) 796{ 797 /* there is no string representation for TSIG rrs */ 798 return LDNS_STATUS_NOT_IMPL; 799} 800 801ldns_status 802ldns_str2rdf_service( ATTR_UNUSED(ldns_rdf **rd) 803 , ATTR_UNUSED(const char *str) 804 ) 805{ 806 /* is this used? is this actually WKS? or SRV? */ 807 return LDNS_STATUS_NOT_IMPL; 808} 809 810static int 811loc_parse_cm(char* my_str, char** endstr, uint8_t* m, uint8_t* e) 812{ 813 /* read <digits>[.<digits>][mM] */ 814 /* into mantissa exponent format for LOC type */ 815 uint32_t meters = 0, cm = 0, val; 816 while (isblank(*my_str)) { 817 my_str++; 818 } 819 meters = (uint32_t)strtol(my_str, &my_str, 10); 820 if (*my_str == '.') { 821 my_str++; 822 cm = (uint32_t)strtol(my_str, &my_str, 10); 823 } 824 if (meters >= 1) { 825 *e = 2; 826 val = meters; 827 } else { 828 *e = 0; 829 val = cm; 830 } 831 while(val >= 10) { 832 (*e)++; 833 val /= 10; 834 } 835 *m = (uint8_t)val; 836 837 if (*e > 9) 838 return 0; 839 if (*my_str == 'm' || *my_str == 'M') { 840 my_str++; 841 } 842 *endstr = my_str; 843 return 1; 844} 845 846ldns_status 847ldns_str2rdf_loc(ldns_rdf **rd, const char *str) 848{ 849 uint32_t latitude = 0; 850 uint32_t longitude = 0; 851 uint32_t altitude = 0; 852 853 uint8_t *data; 854 uint32_t equator = (uint32_t) ldns_power(2, 31); 855 856 uint32_t h = 0; 857 uint32_t m = 0; 858 uint8_t size_b = 1, size_e = 2; 859 uint8_t horiz_pre_b = 1, horiz_pre_e = 6; 860 uint8_t vert_pre_b = 1, vert_pre_e = 3; 861 862 double s = 0.0; 863 bool northerness; 864 bool easterness; 865 866 char *my_str = (char *) str; 867 868 /* only support version 0 */ 869 if (isdigit((int) *my_str)) { 870 h = (uint32_t) strtol(my_str, &my_str, 10); 871 } else { 872 return LDNS_STATUS_INVALID_STR; 873 } 874 875 while (isblank((int) *my_str)) { 876 my_str++; 877 } 878 879 if (isdigit((int) *my_str)) { 880 m = (uint32_t) strtol(my_str, &my_str, 10); 881 } else if (*my_str == 'N' || *my_str == 'S') { 882 goto north; 883 } else { 884 return LDNS_STATUS_INVALID_STR; 885 } 886 887 while (isblank((int) *my_str)) { 888 my_str++; 889 } 890 891 if (isdigit((int) *my_str)) { 892 s = strtod(my_str, &my_str); 893 } 894north: 895 while (isblank((int) *my_str)) { 896 my_str++; 897 } 898 899 if (*my_str == 'N') { 900 northerness = true; 901 } else if (*my_str == 'S') { 902 northerness = false; 903 } else { 904 return LDNS_STATUS_INVALID_STR; 905 } 906 907 my_str++; 908 909 /* store number */ 910 s = 1000.0 * s; 911 /* add a little to make floor in conversion a round */ 912 s += 0.0005; 913 latitude = (uint32_t) s; 914 latitude += 1000 * 60 * m; 915 latitude += 1000 * 60 * 60 * h; 916 if (northerness) { 917 latitude = equator + latitude; 918 } else { 919 latitude = equator - latitude; 920 } 921 while (isblank(*my_str)) { 922 my_str++; 923 } 924 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 == 'E' || *my_str == 'W') { 938 goto east; 939 } else { 940 return LDNS_STATUS_INVALID_STR; 941 } 942 943 while (isblank(*my_str)) { 944 my_str++; 945 } 946 947 if (isdigit((int) *my_str)) { 948 s = strtod(my_str, &my_str); 949 } 950 951east: 952 while (isblank(*my_str)) { 953 my_str++; 954 } 955 956 if (*my_str == 'E') { 957 easterness = true; 958 } else if (*my_str == 'W') { 959 easterness = false; 960 } else { 961 return LDNS_STATUS_INVALID_STR; 962 } 963 964 my_str++; 965 966 /* store number */ 967 s *= 1000.0; 968 /* add a little to make floor in conversion a round */ 969 s += 0.0005; 970 longitude = (uint32_t) s; 971 longitude += 1000 * 60 * m; 972 longitude += 1000 * 60 * 60 * h; 973 974 if (easterness) { 975 longitude += equator; 976 } else { 977 longitude = equator - longitude; 978 } 979 980 altitude = (uint32_t)(strtod(my_str, &my_str)*100.0 + 981 10000000.0 + 0.5); 982 if (*my_str == 'm' || *my_str == 'M') { 983 my_str++; 984 } 985 986 if (strlen(my_str) > 0) { 987 if(!loc_parse_cm(my_str, &my_str, &size_b, &size_e)) 988 return LDNS_STATUS_INVALID_STR; 989 } 990 991 if (strlen(my_str) > 0) { 992 if(!loc_parse_cm(my_str, &my_str, &horiz_pre_b, &horiz_pre_e)) 993 return LDNS_STATUS_INVALID_STR; 994 } 995 996 if (strlen(my_str) > 0) { 997 if(!loc_parse_cm(my_str, &my_str, &vert_pre_b, &vert_pre_e)) 998 return LDNS_STATUS_INVALID_STR; 999 } 1000 1001 data = LDNS_XMALLOC(uint8_t, 16); 1002 if(!data) { 1003 return LDNS_STATUS_MEM_ERR; 1004 } 1005 data[0] = 0; 1006 data[1] = 0; 1007 data[1] = ((size_b << 4) & 0xf0) | (size_e & 0x0f); 1008 data[2] = ((horiz_pre_b << 4) & 0xf0) | (horiz_pre_e & 0x0f); 1009 data[3] = ((vert_pre_b << 4) & 0xf0) | (vert_pre_e & 0x0f); 1010 ldns_write_uint32(data + 4, latitude); 1011 ldns_write_uint32(data + 8, longitude); 1012 ldns_write_uint32(data + 12, altitude); 1013 1014 *rd = ldns_rdf_new_frm_data( 1015 LDNS_RDF_TYPE_LOC, 16, data); 1016 1017 LDNS_FREE(data); 1018 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 1019} 1020 1021ldns_status 1022ldns_str2rdf_wks(ldns_rdf **rd, const char *str) 1023{ 1024 uint8_t *bitmap = NULL; 1025 uint8_t *data; 1026 int bm_len = 0; 1027 1028 struct protoent *proto = NULL; 1029 struct servent *serv = NULL; 1030 int serv_port; 1031 1032 ldns_buffer *str_buf; 1033 1034 char *proto_str = NULL; 1035 char *token; 1036 if(strlen(str) == 0) 1037 token = LDNS_XMALLOC(char, 50); 1038 else token = LDNS_XMALLOC(char, strlen(str)+2); 1039 if(!token) return LDNS_STATUS_MEM_ERR; 1040 1041 str_buf = LDNS_MALLOC(ldns_buffer); 1042 if(!str_buf) {LDNS_FREE(token); return LDNS_STATUS_MEM_ERR;} 1043 ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str)); 1044 if(ldns_buffer_status(str_buf) != LDNS_STATUS_OK) { 1045 LDNS_FREE(str_buf); 1046 LDNS_FREE(token); 1047 return LDNS_STATUS_MEM_ERR; 1048 } 1049 1050 while(ldns_bget_token(str_buf, token, "\t\n ", strlen(str)) > 0) { 1051 if (!proto_str) { 1052 proto_str = strdup(token); 1053 if (!proto_str) { 1054 LDNS_FREE(bitmap); 1055 LDNS_FREE(token); 1056 ldns_buffer_free(str_buf); 1057 return LDNS_STATUS_INVALID_STR; 1058 } 1059 } else { 1060 serv = getservbyname(token, proto_str); 1061 if (serv) { 1062 serv_port = (int) ntohs((uint16_t) serv->s_port); 1063 } else { 1064 serv_port = atoi(token); 1065 } 1066 if (serv_port / 8 >= bm_len) { 1067 uint8_t *b2 = LDNS_XREALLOC(bitmap, uint8_t, (serv_port / 8) + 1); 1068 if(!b2) { 1069 LDNS_FREE(bitmap); 1070 LDNS_FREE(token); 1071 ldns_buffer_free(str_buf); 1072 free(proto_str); 1073 return LDNS_STATUS_INVALID_STR; 1074 } 1075 bitmap = b2; 1076 /* set to zero to be sure */ 1077 for (; bm_len <= serv_port / 8; bm_len++) { 1078 bitmap[bm_len] = 0; 1079 } 1080 } 1081 ldns_set_bit(bitmap + (serv_port / 8), 7 - (serv_port % 8), true); 1082 } 1083 } 1084 1085 if (!proto_str || !bitmap) { 1086 LDNS_FREE(bitmap); 1087 LDNS_FREE(token); 1088 ldns_buffer_free(str_buf); 1089 free(proto_str); 1090 return LDNS_STATUS_INVALID_STR; 1091 } 1092 1093 data = LDNS_XMALLOC(uint8_t, bm_len + 1); 1094 if(!data) { 1095 LDNS_FREE(token); 1096 ldns_buffer_free(str_buf); 1097 LDNS_FREE(bitmap); 1098 free(proto_str); 1099 return LDNS_STATUS_INVALID_STR; 1100 } 1101 if (proto_str) 1102 proto = getprotobyname(proto_str); 1103 if (proto) { 1104 data[0] = (uint8_t) proto->p_proto; 1105 } else if (proto_str) { 1106 data[0] = (uint8_t) atoi(proto_str); 1107 } else { 1108 data[0] = 0; 1109 } 1110 memcpy(data + 1, bitmap, (size_t) bm_len); 1111 1112 *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_WKS, (uint16_t) (bm_len + 1), data); 1113 1114 LDNS_FREE(data); 1115 LDNS_FREE(token); 1116 ldns_buffer_free(str_buf); 1117 LDNS_FREE(bitmap); 1118 free(proto_str); 1119#ifdef HAVE_ENDSERVENT 1120 endservent(); 1121#endif 1122#ifdef HAVE_ENDPROTOENT 1123 endprotoent(); 1124#endif 1125 1126 if(!*rd) return LDNS_STATUS_MEM_ERR; 1127 1128 return LDNS_STATUS_OK; 1129} 1130 1131ldns_status 1132ldns_str2rdf_nsap(ldns_rdf **rd, const char *str) 1133{ 1134 size_t len, i; 1135 char* nsap_str = (char*) str; 1136 1137 /* just a hex string with optional dots? */ 1138 if (str[0] != '0' || str[1] != 'x') { 1139 return LDNS_STATUS_INVALID_STR; 1140 } else { 1141 len = strlen(str); 1142 for (i=0; i < len; i++) { 1143 if (nsap_str[i] == '.') 1144 nsap_str[i] = ' '; 1145 } 1146 return ldns_str2rdf_hex(rd, str+2); 1147 } 1148} 1149 1150ldns_status 1151ldns_str2rdf_atma(ldns_rdf **rd, const char *str) 1152{ 1153 size_t len, i; 1154 char* atma_str = (char*) str; 1155 ldns_status status; 1156 1157 /* just a hex string with optional dots? */ 1158 len = strlen(str); 1159 for (i=0; i < len; i++) { 1160 if (atma_str[i] == '.') 1161 atma_str[i] = ' '; 1162 } 1163 status = ldns_str2rdf_hex(rd, str); 1164 if (status != LDNS_STATUS_OK) { 1165 ; /* probably in e.164 format than */ 1166 } 1167 return status; 1168} 1169 1170ldns_status 1171ldns_str2rdf_ipseckey(ldns_rdf **rd, const char *str) 1172{ 1173 uint8_t precedence = 0; 1174 uint8_t gateway_type = 0; 1175 uint8_t algorithm = 0; 1176 char* gateway = NULL; 1177 char* publickey = NULL; 1178 uint8_t *data; 1179 ldns_buffer *str_buf; 1180 char *token; 1181 int token_count = 0; 1182 int ipseckey_len = 0; 1183 ldns_rdf* gateway_rdf = NULL; 1184 ldns_rdf* publickey_rdf = NULL; 1185 ldns_status status = LDNS_STATUS_OK; 1186 1187 if(strlen(str) == 0) 1188 token = LDNS_XMALLOC(char, 256); 1189 else token = LDNS_XMALLOC(char, strlen(str)+2); 1190 if(!token) return LDNS_STATUS_MEM_ERR; 1191 1192 str_buf = LDNS_MALLOC(ldns_buffer); 1193 if(!str_buf) {LDNS_FREE(token); return LDNS_STATUS_MEM_ERR;} 1194 ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str)); 1195 if(ldns_buffer_status(str_buf) != LDNS_STATUS_OK) { 1196 LDNS_FREE(str_buf); 1197 LDNS_FREE(token); 1198 return LDNS_STATUS_MEM_ERR; 1199 } 1200 while(ldns_bget_token(str_buf, token, "\t\n ", strlen(str)) > 0) { 1201 switch (token_count) { 1202 case 0: 1203 precedence = (uint8_t)atoi(token); 1204 break; 1205 case 1: 1206 gateway_type = (uint8_t)atoi(token); 1207 break; 1208 case 2: 1209 algorithm = (uint8_t)atoi(token); 1210 break; 1211 case 3: 1212 gateway = strdup(token); 1213 if (!gateway || (gateway_type == 0 && 1214 (token[0] != '.' || token[1] != '\0'))) { 1215 LDNS_FREE(gateway); 1216 LDNS_FREE(token); 1217 ldns_buffer_free(str_buf); 1218 return LDNS_STATUS_INVALID_STR; 1219 } 1220 break; 1221 case 4: 1222 publickey = strdup(token); 1223 break; 1224 default: 1225 LDNS_FREE(token); 1226 ldns_buffer_free(str_buf); 1227 return LDNS_STATUS_INVALID_STR; 1228 break; 1229 } 1230 token_count++; 1231 } 1232 1233 if (!gateway || !publickey) { 1234 if (gateway) 1235 LDNS_FREE(gateway); 1236 if (publickey) 1237 LDNS_FREE(publickey); 1238 LDNS_FREE(token); 1239 ldns_buffer_free(str_buf); 1240 return LDNS_STATUS_INVALID_STR; 1241 } 1242 1243 if (gateway_type == 1) { 1244 status = ldns_str2rdf_a(&gateway_rdf, gateway); 1245 } else if (gateway_type == 2) { 1246 status = ldns_str2rdf_aaaa(&gateway_rdf, gateway); 1247 } else if (gateway_type == 3) { 1248 status = ldns_str2rdf_dname(&gateway_rdf, gateway); 1249 } 1250 1251 if (status != LDNS_STATUS_OK) { 1252 if (gateway) 1253 LDNS_FREE(gateway); 1254 if (publickey) 1255 LDNS_FREE(publickey); 1256 LDNS_FREE(token); 1257 ldns_buffer_free(str_buf); 1258 return LDNS_STATUS_INVALID_STR; 1259 } 1260 1261 status = ldns_str2rdf_b64(&publickey_rdf, publickey); 1262 1263 if (status != LDNS_STATUS_OK) { 1264 if (gateway) 1265 LDNS_FREE(gateway); 1266 if (publickey) 1267 LDNS_FREE(publickey); 1268 LDNS_FREE(token); 1269 ldns_buffer_free(str_buf); 1270 if (gateway_rdf) ldns_rdf_free(gateway_rdf); 1271 return LDNS_STATUS_INVALID_STR; 1272 } 1273 1274 /* now copy all into one ipseckey rdf */ 1275 if (gateway_type) 1276 ipseckey_len = 3 + (int)ldns_rdf_size(gateway_rdf) + (int)ldns_rdf_size(publickey_rdf); 1277 else 1278 ipseckey_len = 3 + (int)ldns_rdf_size(publickey_rdf); 1279 1280 data = LDNS_XMALLOC(uint8_t, ipseckey_len); 1281 if(!data) { 1282 if (gateway) 1283 LDNS_FREE(gateway); 1284 if (publickey) 1285 LDNS_FREE(publickey); 1286 LDNS_FREE(token); 1287 ldns_buffer_free(str_buf); 1288 if (gateway_rdf) ldns_rdf_free(gateway_rdf); 1289 if (publickey_rdf) ldns_rdf_free(publickey_rdf); 1290 return LDNS_STATUS_MEM_ERR; 1291 } 1292 1293 data[0] = precedence; 1294 data[1] = gateway_type; 1295 data[2] = algorithm; 1296 1297 if (gateway_type) { 1298 memcpy(data + 3, 1299 ldns_rdf_data(gateway_rdf), ldns_rdf_size(gateway_rdf)); 1300 memcpy(data + 3 + ldns_rdf_size(gateway_rdf), 1301 ldns_rdf_data(publickey_rdf), ldns_rdf_size(publickey_rdf)); 1302 } else { 1303 memcpy(data + 3, 1304 ldns_rdf_data(publickey_rdf), ldns_rdf_size(publickey_rdf)); 1305 } 1306 1307 *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_IPSECKEY, (uint16_t) ipseckey_len, data); 1308 1309 if (gateway) 1310 LDNS_FREE(gateway); 1311 if (publickey) 1312 LDNS_FREE(publickey); 1313 LDNS_FREE(token); 1314 ldns_buffer_free(str_buf); 1315 ldns_rdf_free(gateway_rdf); 1316 ldns_rdf_free(publickey_rdf); 1317 LDNS_FREE(data); 1318 if(!*rd) return LDNS_STATUS_MEM_ERR; 1319 return LDNS_STATUS_OK; 1320} 1321