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