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