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