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 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 */ 260 static int 261 parse_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 */ 295 ldns_status 296 ldns_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 386 ldns_status 387 ldns_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 399 ldns_status 400 ldns_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 413 ldns_status 414 ldns_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 448 ldns_status 449 ldns_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(afdpart); 538 LDNS_FREE(my_ip_str); 539 return LDNS_STATUS_INVALID_STR; 540 } 541 ldns_write_uint16(data, family); 542 data[2] = prefix; 543 data[3] = afdlength; 544 if (negation) { 545 /* set bit 1 of byte 3 */ 546 data[3] = data[3] | 0x80; 547 } 548 549 memcpy(data + 4, afdpart, afdlength); 550 551 *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_APL, afdlength + 4, data); 552 LDNS_FREE(afdpart); 553 LDNS_FREE(data); 554 LDNS_FREE(my_ip_str); 555 556 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 557 } 558 559 ldns_status 560 ldns_str2rdf_b64(ldns_rdf **rd, const char *str) 561 { 562 uint8_t *buffer; 563 int16_t i; 564 565 buffer = LDNS_XMALLOC(uint8_t, ldns_b64_ntop_calculate_size(strlen(str))); 566 if(!buffer) { 567 return LDNS_STATUS_MEM_ERR; 568 } 569 570 i = (uint16_t)ldns_b64_pton((const char*)str, buffer, 571 ldns_b64_ntop_calculate_size(strlen(str))); 572 if (-1 == i) { 573 LDNS_FREE(buffer); 574 return LDNS_STATUS_INVALID_B64; 575 } else { 576 *rd = ldns_rdf_new_frm_data( 577 LDNS_RDF_TYPE_B64, (uint16_t) i, buffer); 578 } 579 LDNS_FREE(buffer); 580 581 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 582 } 583 584 ldns_status 585 ldns_str2rdf_b32_ext(ldns_rdf **rd, const char *str) 586 { 587 uint8_t *buffer; 588 int i; 589 /* first byte contains length of actual b32 data */ 590 uint8_t len = ldns_b32_pton_calculate_size(strlen(str)); 591 buffer = LDNS_XMALLOC(uint8_t, len + 1); 592 if(!buffer) { 593 return LDNS_STATUS_MEM_ERR; 594 } 595 buffer[0] = len; 596 597 i = ldns_b32_pton_extended_hex((const char*)str, strlen(str), buffer + 1, 598 ldns_b32_ntop_calculate_size(strlen(str))); 599 if (i < 0) { 600 LDNS_FREE(buffer); 601 return LDNS_STATUS_INVALID_B32_EXT; 602 } else { 603 *rd = ldns_rdf_new_frm_data( 604 LDNS_RDF_TYPE_B32_EXT, (uint16_t) i + 1, buffer); 605 } 606 LDNS_FREE(buffer); 607 608 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 609 } 610 611 ldns_status 612 ldns_str2rdf_hex(ldns_rdf **rd, const char *str) 613 { 614 uint8_t *t, *t_orig; 615 int i; 616 size_t len; 617 618 len = strlen(str); 619 620 if (len > LDNS_MAX_RDFLEN * 2) { 621 return LDNS_STATUS_LABEL_OVERFLOW; 622 } else { 623 t = LDNS_XMALLOC(uint8_t, (len / 2) + 1); 624 if(!t) { 625 return LDNS_STATUS_MEM_ERR; 626 } 627 t_orig = t; 628 /* Now process octet by octet... */ 629 while (*str) { 630 *t = 0; 631 if (isspace((int) *str)) { 632 str++; 633 } else { 634 for (i = 16; i >= 1; i -= 15) { 635 while (*str && isspace((int) *str)) { str++; } 636 if (*str) { 637 if (isxdigit((int) *str)) { 638 *t += ldns_hexdigit_to_int(*str) * i; 639 } else { 640 LDNS_FREE(t_orig); 641 return LDNS_STATUS_ERR; 642 } 643 ++str; 644 } 645 } 646 ++t; 647 } 648 } 649 *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_HEX, 650 (size_t) (t - t_orig), 651 t_orig); 652 LDNS_FREE(t_orig); 653 } 654 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 655 } 656 657 ldns_status 658 ldns_str2rdf_nsec(ldns_rdf **rd, const char *str) 659 { 660 const char *delimiters = "\n\t "; 661 char *token = LDNS_XMALLOC(char, LDNS_MAX_RDFLEN); 662 ldns_buffer *str_buf; 663 ssize_t c; 664 uint16_t cur_type; 665 size_t type_count = 0; 666 ldns_rr_type type_list[65536]; 667 if(!token) return LDNS_STATUS_MEM_ERR; 668 if(rd == NULL) { 669 LDNS_FREE(token); 670 return LDNS_STATUS_NULL; 671 } 672 673 str_buf = LDNS_MALLOC(ldns_buffer); 674 if(!str_buf) { 675 LDNS_FREE(token); 676 return LDNS_STATUS_MEM_ERR; 677 } 678 ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str)); 679 if(ldns_buffer_status(str_buf) != LDNS_STATUS_OK) { 680 LDNS_FREE(str_buf); 681 LDNS_FREE(token); 682 return LDNS_STATUS_MEM_ERR; 683 } 684 685 while ((c = ldns_bget_token(str_buf, token, delimiters, LDNS_MAX_RDFLEN)) != -1 && c != 0) { 686 if(type_count >= sizeof(type_list)) { 687 LDNS_FREE(str_buf); 688 LDNS_FREE(token); 689 return LDNS_STATUS_ERR; 690 } 691 cur_type = ldns_get_rr_type_by_name(token); 692 type_list[type_count] = cur_type; 693 type_count++; 694 } 695 696 *rd = ldns_dnssec_create_nsec_bitmap(type_list, 697 type_count, 698 LDNS_RR_TYPE_NSEC); 699 700 LDNS_FREE(token); 701 ldns_buffer_free(str_buf); 702 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 703 } 704 705 ldns_status 706 ldns_str2rdf_type(ldns_rdf **rd, const char *str) 707 { 708 uint16_t type; 709 type = htons(ldns_get_rr_type_by_name(str)); 710 /* ldns_rr_type is a 16 bit value */ 711 *rd = ldns_rdf_new_frm_data( 712 LDNS_RDF_TYPE_TYPE, sizeof(uint16_t), &type); 713 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 714 } 715 716 ldns_status 717 ldns_str2rdf_class(ldns_rdf **rd, const char *str) 718 { 719 uint16_t klass; 720 klass = htons(ldns_get_rr_class_by_name(str)); 721 /* class is 16 bit */ 722 *rd = ldns_rdf_new_frm_data( 723 LDNS_RDF_TYPE_CLASS, sizeof(uint16_t), &klass); 724 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 725 } 726 727 /* An certificate alg field can either be specified as a 8 bits number 728 * or by its symbolic name. Handle both 729 */ 730 ldns_status 731 ldns_str2rdf_cert_alg(ldns_rdf **rd, const char *str) 732 { 733 ldns_lookup_table *lt; 734 ldns_status st; 735 uint8_t idd[2]; 736 lt = ldns_lookup_by_name(ldns_cert_algorithms, str); 737 st = LDNS_STATUS_OK; 738 739 if (lt) { 740 ldns_write_uint16(idd, (uint16_t) lt->id); 741 *rd = ldns_rdf_new_frm_data( 742 LDNS_RDF_TYPE_INT16, sizeof(uint16_t), idd); 743 if (!*rd) { 744 st = LDNS_STATUS_ERR; 745 } 746 } else { 747 /* try as-is (a number) */ 748 st = ldns_str2rdf_int16(rd, str); 749 if (st == LDNS_STATUS_OK && 750 ldns_rdf2native_int16(*rd) == 0) { 751 st = LDNS_STATUS_CERT_BAD_ALGORITHM; 752 } 753 } 754 755 return st; 756 } 757 758 /* An alg field can either be specified as a 8 bits number 759 * or by its symbolic name. Handle both 760 */ 761 ldns_status 762 ldns_str2rdf_alg(ldns_rdf **rd, const char *str) 763 { 764 ldns_lookup_table *lt; 765 ldns_status st; 766 767 lt = ldns_lookup_by_name(ldns_algorithms, str); 768 st = LDNS_STATUS_OK; 769 770 if (lt) { 771 /* it was given as a integer */ 772 *rd = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, (uint8_t) lt->id); 773 if (!*rd) { 774 st = LDNS_STATUS_ERR; 775 } 776 } else { 777 /* try as-is (a number) */ 778 st = ldns_str2rdf_int8(rd, str); 779 } 780 return st; 781 } 782 783 ldns_status 784 ldns_str2rdf_unknown( ATTR_UNUSED(ldns_rdf **rd) 785 , ATTR_UNUSED(const char *str) 786 ) 787 { 788 /* this should be caught in an earlier time (general str2host for 789 rr's */ 790 return LDNS_STATUS_NOT_IMPL; 791 } 792 793 ldns_status 794 ldns_str2rdf_tsig( ATTR_UNUSED(ldns_rdf **rd) 795 , ATTR_UNUSED(const char *str) 796 ) 797 { 798 /* there is no string representation for TSIG rrs */ 799 return LDNS_STATUS_NOT_IMPL; 800 } 801 802 ldns_status 803 ldns_str2rdf_service( ATTR_UNUSED(ldns_rdf **rd) 804 , ATTR_UNUSED(const char *str) 805 ) 806 { 807 /* is this used? is this actually WKS? or SRV? */ 808 return LDNS_STATUS_NOT_IMPL; 809 } 810 811 static int 812 loc_parse_cm(char* my_str, char** endstr, uint8_t* m, uint8_t* e) 813 { 814 /* read <digits>[.<digits>][mM] */ 815 /* into mantissa exponent format for LOC type */ 816 uint32_t meters = 0, cm = 0, val; 817 while (isblank(*my_str)) { 818 my_str++; 819 } 820 meters = (uint32_t)strtol(my_str, &my_str, 10); 821 if (*my_str == '.') { 822 my_str++; 823 cm = (uint32_t)strtol(my_str, &my_str, 10); 824 } 825 if (meters >= 1) { 826 *e = 2; 827 val = meters; 828 } else { 829 *e = 0; 830 val = cm; 831 } 832 while(val >= 10) { 833 (*e)++; 834 val /= 10; 835 } 836 *m = (uint8_t)val; 837 838 if (*e > 9) 839 return 0; 840 if (*my_str == 'm' || *my_str == 'M') { 841 my_str++; 842 } 843 *endstr = my_str; 844 return 1; 845 } 846 847 ldns_status 848 ldns_str2rdf_loc(ldns_rdf **rd, const char *str) 849 { 850 uint32_t latitude = 0; 851 uint32_t longitude = 0; 852 uint32_t altitude = 0; 853 854 uint8_t *data; 855 uint32_t equator = (uint32_t) ldns_power(2, 31); 856 857 uint32_t h = 0; 858 uint32_t m = 0; 859 uint8_t size_b = 1, size_e = 2; 860 uint8_t horiz_pre_b = 1, horiz_pre_e = 6; 861 uint8_t vert_pre_b = 1, vert_pre_e = 3; 862 863 double s = 0.0; 864 bool northerness; 865 bool easterness; 866 867 char *my_str = (char *) str; 868 869 /* only support version 0 */ 870 if (isdigit((int) *my_str)) { 871 h = (uint32_t) strtol(my_str, &my_str, 10); 872 } else { 873 return LDNS_STATUS_INVALID_STR; 874 } 875 876 while (isblank((int) *my_str)) { 877 my_str++; 878 } 879 880 if (isdigit((int) *my_str)) { 881 m = (uint32_t) strtol(my_str, &my_str, 10); 882 } else if (*my_str == 'N' || *my_str == 'S') { 883 goto north; 884 } else { 885 return LDNS_STATUS_INVALID_STR; 886 } 887 888 while (isblank((int) *my_str)) { 889 my_str++; 890 } 891 892 if (isdigit((int) *my_str)) { 893 s = strtod(my_str, &my_str); 894 } 895 north: 896 while (isblank((int) *my_str)) { 897 my_str++; 898 } 899 900 if (*my_str == 'N') { 901 northerness = true; 902 } else if (*my_str == 'S') { 903 northerness = false; 904 } else { 905 return LDNS_STATUS_INVALID_STR; 906 } 907 908 my_str++; 909 910 /* store number */ 911 s = 1000.0 * s; 912 /* add a little to make floor in conversion a round */ 913 s += 0.0005; 914 latitude = (uint32_t) s; 915 latitude += 1000 * 60 * m; 916 latitude += 1000 * 60 * 60 * h; 917 if (northerness) { 918 latitude = equator + latitude; 919 } else { 920 latitude = equator - latitude; 921 } 922 while (isblank(*my_str)) { 923 my_str++; 924 } 925 926 if (isdigit((int) *my_str)) { 927 h = (uint32_t) strtol(my_str, &my_str, 10); 928 } else { 929 return LDNS_STATUS_INVALID_STR; 930 } 931 932 while (isblank((int) *my_str)) { 933 my_str++; 934 } 935 936 if (isdigit((int) *my_str)) { 937 m = (uint32_t) strtol(my_str, &my_str, 10); 938 } else if (*my_str == 'E' || *my_str == 'W') { 939 goto east; 940 } else { 941 return LDNS_STATUS_INVALID_STR; 942 } 943 944 while (isblank(*my_str)) { 945 my_str++; 946 } 947 948 if (isdigit((int) *my_str)) { 949 s = strtod(my_str, &my_str); 950 } 951 952 east: 953 while (isblank(*my_str)) { 954 my_str++; 955 } 956 957 if (*my_str == 'E') { 958 easterness = true; 959 } else if (*my_str == 'W') { 960 easterness = false; 961 } else { 962 return LDNS_STATUS_INVALID_STR; 963 } 964 965 my_str++; 966 967 /* store number */ 968 s *= 1000.0; 969 /* add a little to make floor in conversion a round */ 970 s += 0.0005; 971 longitude = (uint32_t) s; 972 longitude += 1000 * 60 * m; 973 longitude += 1000 * 60 * 60 * h; 974 975 if (easterness) { 976 longitude += equator; 977 } else { 978 longitude = equator - longitude; 979 } 980 981 altitude = (uint32_t)(strtod(my_str, &my_str)*100.0 + 982 10000000.0 + 0.5); 983 if (*my_str == 'm' || *my_str == 'M') { 984 my_str++; 985 } 986 987 if (strlen(my_str) > 0) { 988 if(!loc_parse_cm(my_str, &my_str, &size_b, &size_e)) 989 return LDNS_STATUS_INVALID_STR; 990 } 991 992 if (strlen(my_str) > 0) { 993 if(!loc_parse_cm(my_str, &my_str, &horiz_pre_b, &horiz_pre_e)) 994 return LDNS_STATUS_INVALID_STR; 995 } 996 997 if (strlen(my_str) > 0) { 998 if(!loc_parse_cm(my_str, &my_str, &vert_pre_b, &vert_pre_e)) 999 return LDNS_STATUS_INVALID_STR; 1000 } 1001 1002 data = LDNS_XMALLOC(uint8_t, 16); 1003 if(!data) { 1004 return LDNS_STATUS_MEM_ERR; 1005 } 1006 data[0] = 0; 1007 data[1] = 0; 1008 data[1] = ((size_b << 4) & 0xf0) | (size_e & 0x0f); 1009 data[2] = ((horiz_pre_b << 4) & 0xf0) | (horiz_pre_e & 0x0f); 1010 data[3] = ((vert_pre_b << 4) & 0xf0) | (vert_pre_e & 0x0f); 1011 ldns_write_uint32(data + 4, latitude); 1012 ldns_write_uint32(data + 8, longitude); 1013 ldns_write_uint32(data + 12, altitude); 1014 1015 *rd = ldns_rdf_new_frm_data( 1016 LDNS_RDF_TYPE_LOC, 16, data); 1017 1018 LDNS_FREE(data); 1019 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 1020 } 1021 1022 ldns_status 1023 ldns_str2rdf_wks(ldns_rdf **rd, const char *str) 1024 { 1025 uint8_t *bitmap = NULL; 1026 uint8_t *data; 1027 int bm_len = 0; 1028 1029 struct protoent *proto = NULL; 1030 struct servent *serv = NULL; 1031 int serv_port; 1032 1033 ldns_buffer *str_buf; 1034 1035 char *proto_str = NULL; 1036 char *token; 1037 if(strlen(str) == 0) 1038 token = LDNS_XMALLOC(char, 50); 1039 else token = LDNS_XMALLOC(char, strlen(str)+2); 1040 if(!token) return LDNS_STATUS_MEM_ERR; 1041 1042 str_buf = LDNS_MALLOC(ldns_buffer); 1043 if(!str_buf) {LDNS_FREE(token); return LDNS_STATUS_MEM_ERR;} 1044 ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str)); 1045 if(ldns_buffer_status(str_buf) != LDNS_STATUS_OK) { 1046 LDNS_FREE(str_buf); 1047 LDNS_FREE(token); 1048 return LDNS_STATUS_MEM_ERR; 1049 } 1050 1051 while(ldns_bget_token(str_buf, token, "\t\n ", strlen(str)) > 0) { 1052 if (!proto_str) { 1053 proto_str = strdup(token); 1054 if (!proto_str) { 1055 LDNS_FREE(bitmap); 1056 LDNS_FREE(token); 1057 ldns_buffer_free(str_buf); 1058 return LDNS_STATUS_INVALID_STR; 1059 } 1060 } else { 1061 serv = getservbyname(token, proto_str); 1062 if (serv) { 1063 serv_port = (int) ntohs((uint16_t) serv->s_port); 1064 } else { 1065 serv_port = atoi(token); 1066 } 1067 if (serv_port / 8 >= bm_len) { 1068 uint8_t *b2 = LDNS_XREALLOC(bitmap, uint8_t, (serv_port / 8) + 1); 1069 if(!b2) { 1070 LDNS_FREE(bitmap); 1071 LDNS_FREE(token); 1072 ldns_buffer_free(str_buf); 1073 free(proto_str); 1074 return LDNS_STATUS_INVALID_STR; 1075 } 1076 bitmap = b2; 1077 /* set to zero to be sure */ 1078 for (; bm_len <= serv_port / 8; bm_len++) { 1079 bitmap[bm_len] = 0; 1080 } 1081 } 1082 ldns_set_bit(bitmap + (serv_port / 8), 7 - (serv_port % 8), true); 1083 } 1084 } 1085 1086 if (!proto_str || !bitmap) { 1087 LDNS_FREE(bitmap); 1088 LDNS_FREE(token); 1089 ldns_buffer_free(str_buf); 1090 free(proto_str); 1091 return LDNS_STATUS_INVALID_STR; 1092 } 1093 1094 data = LDNS_XMALLOC(uint8_t, bm_len + 1); 1095 if(!data) { 1096 LDNS_FREE(token); 1097 ldns_buffer_free(str_buf); 1098 LDNS_FREE(bitmap); 1099 free(proto_str); 1100 return LDNS_STATUS_INVALID_STR; 1101 } 1102 if (proto_str) 1103 proto = getprotobyname(proto_str); 1104 if (proto) { 1105 data[0] = (uint8_t) proto->p_proto; 1106 } else if (proto_str) { 1107 data[0] = (uint8_t) atoi(proto_str); 1108 } 1109 memcpy(data + 1, bitmap, (size_t) bm_len); 1110 1111 *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_WKS, (uint16_t) (bm_len + 1), data); 1112 1113 LDNS_FREE(data); 1114 LDNS_FREE(token); 1115 ldns_buffer_free(str_buf); 1116 LDNS_FREE(bitmap); 1117 free(proto_str); 1118 #ifdef HAVE_ENDSERVENT 1119 endservent(); 1120 #endif 1121 #ifdef HAVE_ENDPROTOENT 1122 endprotoent(); 1123 #endif 1124 1125 if(!*rd) return LDNS_STATUS_MEM_ERR; 1126 1127 return LDNS_STATUS_OK; 1128 } 1129 1130 ldns_status 1131 ldns_str2rdf_nsap(ldns_rdf **rd, const char *str) 1132 { 1133 size_t len, i; 1134 char* nsap_str = (char*) str; 1135 1136 /* just a hex string with optional dots? */ 1137 if (str[0] != '0' || str[1] != 'x') { 1138 return LDNS_STATUS_INVALID_STR; 1139 } else { 1140 len = strlen(str); 1141 for (i=0; i < len; i++) { 1142 if (nsap_str[i] == '.') 1143 nsap_str[i] = ' '; 1144 } 1145 return ldns_str2rdf_hex(rd, str+2); 1146 } 1147 } 1148 1149 ldns_status 1150 ldns_str2rdf_atma(ldns_rdf **rd, const char *str) 1151 { 1152 size_t len, i; 1153 char* atma_str = (char*) str; 1154 ldns_status status; 1155 1156 /* just a hex string with optional dots? */ 1157 len = strlen(str); 1158 for (i=0; i < len; i++) { 1159 if (atma_str[i] == '.') 1160 atma_str[i] = ' '; 1161 } 1162 status = ldns_str2rdf_hex(rd, str); 1163 if (status != LDNS_STATUS_OK) { 1164 ; /* probably in e.164 format than */ 1165 } 1166 return status; 1167 } 1168 1169 ldns_status 1170 ldns_str2rdf_ipseckey(ldns_rdf **rd, const char *str) 1171 { 1172 uint8_t precedence = 0; 1173 uint8_t gateway_type = 0; 1174 uint8_t algorithm = 0; 1175 char* gateway = NULL; 1176 char* publickey = NULL; 1177 uint8_t *data; 1178 ldns_buffer *str_buf; 1179 char *token; 1180 int token_count = 0; 1181 int ipseckey_len = 0; 1182 ldns_rdf* gateway_rdf = NULL; 1183 ldns_rdf* publickey_rdf = NULL; 1184 ldns_status status = LDNS_STATUS_OK; 1185 1186 if(strlen(str) == 0) 1187 token = LDNS_XMALLOC(char, 256); 1188 else token = LDNS_XMALLOC(char, strlen(str)+2); 1189 if(!token) return LDNS_STATUS_MEM_ERR; 1190 1191 str_buf = LDNS_MALLOC(ldns_buffer); 1192 if(!str_buf) {LDNS_FREE(token); return LDNS_STATUS_MEM_ERR;} 1193 ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str)); 1194 if(ldns_buffer_status(str_buf) != LDNS_STATUS_OK) { 1195 LDNS_FREE(str_buf); 1196 LDNS_FREE(token); 1197 return LDNS_STATUS_MEM_ERR; 1198 } 1199 while(ldns_bget_token(str_buf, token, "\t\n ", strlen(str)) > 0) { 1200 switch (token_count) { 1201 case 0: 1202 precedence = (uint8_t)atoi(token); 1203 break; 1204 case 1: 1205 gateway_type = (uint8_t)atoi(token); 1206 break; 1207 case 2: 1208 algorithm = (uint8_t)atoi(token); 1209 break; 1210 case 3: 1211 gateway = strdup(token); 1212 if (!gateway || (gateway_type == 0 && 1213 (token[0] != '.' || token[1] != '\0'))) { 1214 LDNS_FREE(gateway); 1215 LDNS_FREE(token); 1216 ldns_buffer_free(str_buf); 1217 return LDNS_STATUS_INVALID_STR; 1218 } 1219 break; 1220 case 4: 1221 publickey = strdup(token); 1222 break; 1223 default: 1224 LDNS_FREE(token); 1225 ldns_buffer_free(str_buf); 1226 return LDNS_STATUS_INVALID_STR; 1227 break; 1228 } 1229 token_count++; 1230 } 1231 1232 if (!gateway || !publickey) { 1233 if (gateway) 1234 LDNS_FREE(gateway); 1235 if (publickey) 1236 LDNS_FREE(publickey); 1237 LDNS_FREE(token); 1238 ldns_buffer_free(str_buf); 1239 return LDNS_STATUS_INVALID_STR; 1240 } 1241 1242 if (gateway_type == 1) { 1243 status = ldns_str2rdf_a(&gateway_rdf, gateway); 1244 } else if (gateway_type == 2) { 1245 status = ldns_str2rdf_aaaa(&gateway_rdf, gateway); 1246 } else if (gateway_type == 3) { 1247 status = ldns_str2rdf_dname(&gateway_rdf, gateway); 1248 } 1249 1250 if (status != LDNS_STATUS_OK) { 1251 if (gateway) 1252 LDNS_FREE(gateway); 1253 if (publickey) 1254 LDNS_FREE(publickey); 1255 LDNS_FREE(token); 1256 ldns_buffer_free(str_buf); 1257 return LDNS_STATUS_INVALID_STR; 1258 } 1259 1260 status = ldns_str2rdf_b64(&publickey_rdf, publickey); 1261 1262 if (status != LDNS_STATUS_OK) { 1263 if (gateway) 1264 LDNS_FREE(gateway); 1265 if (publickey) 1266 LDNS_FREE(publickey); 1267 LDNS_FREE(token); 1268 ldns_buffer_free(str_buf); 1269 if (gateway_rdf) ldns_rdf_free(gateway_rdf); 1270 return LDNS_STATUS_INVALID_STR; 1271 } 1272 1273 /* now copy all into one ipseckey rdf */ 1274 if (gateway_type) 1275 ipseckey_len = 3 + (int)ldns_rdf_size(gateway_rdf) + (int)ldns_rdf_size(publickey_rdf); 1276 else 1277 ipseckey_len = 3 + (int)ldns_rdf_size(publickey_rdf); 1278 1279 data = LDNS_XMALLOC(uint8_t, ipseckey_len); 1280 if(!data) { 1281 if (gateway) 1282 LDNS_FREE(gateway); 1283 if (publickey) 1284 LDNS_FREE(publickey); 1285 LDNS_FREE(token); 1286 ldns_buffer_free(str_buf); 1287 if (gateway_rdf) ldns_rdf_free(gateway_rdf); 1288 if (publickey_rdf) ldns_rdf_free(publickey_rdf); 1289 return LDNS_STATUS_MEM_ERR; 1290 } 1291 1292 data[0] = precedence; 1293 data[1] = gateway_type; 1294 data[2] = algorithm; 1295 1296 if (gateway_type) { 1297 memcpy(data + 3, 1298 ldns_rdf_data(gateway_rdf), ldns_rdf_size(gateway_rdf)); 1299 memcpy(data + 3 + ldns_rdf_size(gateway_rdf), 1300 ldns_rdf_data(publickey_rdf), ldns_rdf_size(publickey_rdf)); 1301 } else { 1302 memcpy(data + 3, 1303 ldns_rdf_data(publickey_rdf), ldns_rdf_size(publickey_rdf)); 1304 } 1305 1306 *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_IPSECKEY, (uint16_t) ipseckey_len, data); 1307 1308 if (gateway) 1309 LDNS_FREE(gateway); 1310 if (publickey) 1311 LDNS_FREE(publickey); 1312 LDNS_FREE(token); 1313 ldns_buffer_free(str_buf); 1314 ldns_rdf_free(gateway_rdf); 1315 ldns_rdf_free(publickey_rdf); 1316 LDNS_FREE(data); 1317 if(!*rd) return LDNS_STATUS_MEM_ERR; 1318 return LDNS_STATUS_OK; 1319 } 1320