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