1 /* 2 * util.c 3 * 4 * some general memory functions 5 * 6 * a Net::DNS like library for C 7 * 8 * (c) NLnet Labs, 2004-2006 9 * 10 * See the file LICENSE for the license 11 */ 12 13 #include <ldns/config.h> 14 15 #include <ldns/rdata.h> 16 #include <ldns/rr.h> 17 #include <ldns/util.h> 18 #include <strings.h> 19 #include <stdlib.h> 20 #include <stdio.h> 21 #include <sys/time.h> 22 #include <time.h> 23 #include <ctype.h> 24 25 #ifdef HAVE_SSL 26 #include <openssl/rand.h> 27 #endif 28 29 ldns_lookup_table * 30 ldns_lookup_by_name(ldns_lookup_table *table, const char *name) 31 { 32 while (table->name != NULL) { 33 if (strcasecmp(name, table->name) == 0) 34 return table; 35 table++; 36 } 37 return NULL; 38 } 39 40 ldns_lookup_table * 41 ldns_lookup_by_id(ldns_lookup_table *table, int id) 42 { 43 while (table->name != NULL) { 44 if (table->id == id) 45 return table; 46 table++; 47 } 48 return NULL; 49 } 50 51 int 52 ldns_get_bit(uint8_t bits[], size_t index) 53 { 54 /* 55 * The bits are counted from left to right, so bit #0 is the 56 * left most bit. 57 */ 58 return (int) (bits[index / 8] & (1 << (7 - index % 8))); 59 } 60 61 int 62 ldns_get_bit_r(uint8_t bits[], size_t index) 63 { 64 /* 65 * The bits are counted from right to left, so bit #0 is the 66 * right most bit. 67 */ 68 return (int) bits[index / 8] & (1 << (index % 8)); 69 } 70 71 void 72 ldns_set_bit(uint8_t *byte, int bit_nr, bool value) 73 { 74 /* 75 * The bits are counted from right to left, so bit #0 is the 76 * right most bit. 77 */ 78 if (bit_nr >= 0 && bit_nr < 8) { 79 if (value) { 80 *byte = *byte | (0x01 << bit_nr); 81 } else { 82 *byte = *byte & ~(0x01 << bit_nr); 83 } 84 } 85 } 86 87 int 88 ldns_hexdigit_to_int(char ch) 89 { 90 switch (ch) { 91 case '0': return 0; 92 case '1': return 1; 93 case '2': return 2; 94 case '3': return 3; 95 case '4': return 4; 96 case '5': return 5; 97 case '6': return 6; 98 case '7': return 7; 99 case '8': return 8; 100 case '9': return 9; 101 case 'a': case 'A': return 10; 102 case 'b': case 'B': return 11; 103 case 'c': case 'C': return 12; 104 case 'd': case 'D': return 13; 105 case 'e': case 'E': return 14; 106 case 'f': case 'F': return 15; 107 default: 108 return -1; 109 } 110 } 111 112 char 113 ldns_int_to_hexdigit(int i) 114 { 115 switch (i) { 116 case 0: return '0'; 117 case 1: return '1'; 118 case 2: return '2'; 119 case 3: return '3'; 120 case 4: return '4'; 121 case 5: return '5'; 122 case 6: return '6'; 123 case 7: return '7'; 124 case 8: return '8'; 125 case 9: return '9'; 126 case 10: return 'a'; 127 case 11: return 'b'; 128 case 12: return 'c'; 129 case 13: return 'd'; 130 case 14: return 'e'; 131 case 15: return 'f'; 132 default: 133 abort(); 134 } 135 } 136 137 int 138 ldns_hexstring_to_data(uint8_t *data, const char *str) 139 { 140 size_t i; 141 142 if (!str || !data) { 143 return -1; 144 } 145 146 if (strlen(str) % 2 != 0) { 147 return -2; 148 } 149 150 for (i = 0; i < strlen(str) / 2; i++) { 151 data[i] = 152 16 * (uint8_t) ldns_hexdigit_to_int(str[i*2]) + 153 (uint8_t) ldns_hexdigit_to_int(str[i*2 + 1]); 154 } 155 156 return (int) i; 157 } 158 159 const char * 160 ldns_version(void) 161 { 162 return (char*)LDNS_VERSION; 163 } 164 165 /* Number of days per month (except for February in leap years). */ 166 static const int mdays[] = { 167 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 168 }; 169 170 #define LDNS_MOD(x,y) (((x) % (y) < 0) ? ((x) % (y) + (y)) : ((x) % (y))) 171 #define LDNS_DIV(x,y) (((x) % (y) < 0) ? ((x) / (y) - 1 ) : ((x) / (y))) 172 173 static int 174 is_leap_year(int year) 175 { 176 return LDNS_MOD(year, 4) == 0 && (LDNS_MOD(year, 100) != 0 177 || LDNS_MOD(year, 400) == 0); 178 } 179 180 static int 181 leap_days(int y1, int y2) 182 { 183 --y1; 184 --y2; 185 return (LDNS_DIV(y2, 4) - LDNS_DIV(y1, 4)) - 186 (LDNS_DIV(y2, 100) - LDNS_DIV(y1, 100)) + 187 (LDNS_DIV(y2, 400) - LDNS_DIV(y1, 400)); 188 } 189 190 /* 191 * Code adapted from Python 2.4.1 sources (Lib/calendar.py). 192 */ 193 time_t 194 ldns_mktime_from_utc(const struct tm *tm) 195 { 196 int year = 1900 + tm->tm_year; 197 time_t days = 365 * ((time_t) year - 1970) + leap_days(1970, year); 198 time_t hours; 199 time_t minutes; 200 time_t seconds; 201 int i; 202 203 for (i = 0; i < tm->tm_mon; ++i) { 204 days += mdays[i]; 205 } 206 if (tm->tm_mon > 1 && is_leap_year(year)) { 207 ++days; 208 } 209 days += tm->tm_mday - 1; 210 211 hours = days * 24 + tm->tm_hour; 212 minutes = hours * 60 + tm->tm_min; 213 seconds = minutes * 60 + tm->tm_sec; 214 215 return seconds; 216 } 217 218 time_t 219 mktime_from_utc(const struct tm *tm) 220 { 221 return ldns_mktime_from_utc(tm); 222 } 223 224 #if SIZEOF_TIME_T <= 4 225 226 static void 227 ldns_year_and_yday_from_days_since_epoch(int64_t days, struct tm *result) 228 { 229 int year = 1970; 230 int new_year; 231 232 while (days < 0 || days >= (int64_t) (is_leap_year(year) ? 366 : 365)) { 233 new_year = year + (int) LDNS_DIV(days, 365); 234 days -= (new_year - year) * 365; 235 days -= leap_days(year, new_year); 236 year = new_year; 237 } 238 result->tm_year = year; 239 result->tm_yday = (int) days; 240 } 241 242 /* Number of days per month in a leap year. */ 243 static const int leap_year_mdays[] = { 244 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 245 }; 246 247 static void 248 ldns_mon_and_mday_from_year_and_yday(struct tm *result) 249 { 250 int idays = result->tm_yday; 251 const int *mon_lengths = is_leap_year(result->tm_year) ? 252 leap_year_mdays : mdays; 253 254 result->tm_mon = 0; 255 while (idays >= mon_lengths[result->tm_mon]) { 256 idays -= mon_lengths[result->tm_mon++]; 257 } 258 result->tm_mday = idays + 1; 259 } 260 261 static void 262 ldns_wday_from_year_and_yday(struct tm *result) 263 { 264 result->tm_wday = 4 /* 1-1-1970 was a thursday */ 265 + LDNS_MOD((result->tm_year - 1970), 7) * LDNS_MOD(365, 7) 266 + leap_days(1970, result->tm_year) 267 + result->tm_yday; 268 result->tm_wday = LDNS_MOD(result->tm_wday, 7); 269 if (result->tm_wday < 0) { 270 result->tm_wday += 7; 271 } 272 } 273 274 static struct tm * 275 ldns_gmtime64_r(int64_t clock, struct tm *result) 276 { 277 result->tm_isdst = 0; 278 result->tm_sec = (int) LDNS_MOD(clock, 60); 279 clock = LDNS_DIV(clock, 60); 280 result->tm_min = (int) LDNS_MOD(clock, 60); 281 clock = LDNS_DIV(clock, 60); 282 result->tm_hour = (int) LDNS_MOD(clock, 24); 283 clock = LDNS_DIV(clock, 24); 284 285 ldns_year_and_yday_from_days_since_epoch(clock, result); 286 ldns_mon_and_mday_from_year_and_yday(result); 287 ldns_wday_from_year_and_yday(result); 288 result->tm_year -= 1900; 289 290 return result; 291 } 292 293 #endif /* SIZEOF_TIME_T <= 4 */ 294 295 static int64_t 296 ldns_serial_arithmitics_time(int32_t time, time_t now) 297 { 298 int32_t offset = time - (int32_t) now; 299 return (int64_t) now + offset; 300 } 301 302 303 struct tm * 304 ldns_serial_arithmitics_gmtime_r(int32_t time, time_t now, struct tm *result) 305 { 306 #if SIZEOF_TIME_T <= 4 307 int64_t secs_since_epoch = ldns_serial_arithmitics_time(time, now); 308 return ldns_gmtime64_r(secs_since_epoch, result); 309 #else 310 time_t secs_since_epoch = ldns_serial_arithmitics_time(time, now); 311 return gmtime_r(&secs_since_epoch, result); 312 #endif 313 } 314 315 /** 316 * Init the random source 317 * applications should call this if they need entropy data within ldns 318 * If openSSL is available, it is automatically seeded from /dev/urandom 319 * or /dev/random 320 * 321 * If you need more entropy, or have no openssl available, this function 322 * MUST be called at the start of the program 323 * 324 * If openssl *is* available, this function just adds more entropy 325 **/ 326 int 327 ldns_init_random(FILE *fd, unsigned int size) 328 { 329 /* if fp is given, seed srandom with data from file 330 otherwise use /dev/urandom */ 331 FILE *rand_f; 332 uint8_t *seed; 333 size_t read = 0; 334 unsigned int seed_i; 335 struct timeval tv; 336 337 /* we'll need at least sizeof(unsigned int) bytes for the 338 standard prng seed */ 339 if (size < (unsigned int) sizeof(seed_i)){ 340 size = (unsigned int) sizeof(seed_i); 341 } 342 343 seed = LDNS_XMALLOC(uint8_t, size); 344 if(!seed) { 345 return 1; 346 } 347 348 if (!fd) { 349 if ((rand_f = fopen("/dev/urandom", "r")) == NULL) { 350 /* no readable /dev/urandom, try /dev/random */ 351 if ((rand_f = fopen("/dev/random", "r")) == NULL) { 352 /* no readable /dev/random either, and no entropy 353 source given. we'll have to improvise */ 354 for (read = 0; read < size; read++) { 355 gettimeofday(&tv, NULL); 356 seed[read] = (uint8_t) (tv.tv_usec % 256); 357 } 358 } else { 359 read = fread(seed, 1, size, rand_f); 360 } 361 } else { 362 read = fread(seed, 1, size, rand_f); 363 } 364 } else { 365 rand_f = fd; 366 read = fread(seed, 1, size, rand_f); 367 } 368 369 if (read < size) { 370 LDNS_FREE(seed); 371 if (!fd) fclose(rand_f); 372 return 1; 373 } else { 374 #ifdef HAVE_SSL 375 /* Seed the OpenSSL prng (most systems have it seeded 376 automatically, in that case this call just adds entropy */ 377 RAND_seed(seed, (int) size); 378 #else 379 /* Seed the standard prng, only uses the first 380 * unsigned sizeof(unsiged int) bytes found in the entropy pool 381 */ 382 memcpy(&seed_i, seed, sizeof(seed_i)); 383 srandom(seed_i); 384 #endif 385 LDNS_FREE(seed); 386 } 387 388 if (!fd) { 389 if (rand_f) fclose(rand_f); 390 } 391 392 return 0; 393 } 394 395 /** 396 * Get random number. 397 * 398 */ 399 uint16_t 400 ldns_get_random(void) 401 { 402 uint16_t rid = 0; 403 #ifdef HAVE_SSL 404 if (RAND_bytes((unsigned char*)&rid, 2) != 1) { 405 rid = (uint16_t) random(); 406 } 407 #else 408 rid = (uint16_t) random(); 409 #endif 410 return rid; 411 } 412 413 /* 414 * BubbleBabble code taken from OpenSSH 415 * Copyright (c) 2001 Carsten Raskgaard. All rights reserved. 416 */ 417 char * 418 ldns_bubblebabble(uint8_t *data, size_t len) 419 { 420 char vowels[] = { 'a', 'e', 'i', 'o', 'u', 'y' }; 421 char consonants[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm', 422 'n', 'p', 'r', 's', 't', 'v', 'z', 'x' }; 423 size_t i, j = 0, rounds, seed = 1; 424 char *retval; 425 426 rounds = (len / 2) + 1; 427 retval = LDNS_XMALLOC(char, rounds * 6); 428 if(!retval) return NULL; 429 retval[j++] = 'x'; 430 for (i = 0; i < rounds; i++) { 431 size_t idx0, idx1, idx2, idx3, idx4; 432 if ((i + 1 < rounds) || (len % 2 != 0)) { 433 idx0 = (((((size_t)(data[2 * i])) >> 6) & 3) + 434 seed) % 6; 435 idx1 = (((size_t)(data[2 * i])) >> 2) & 15; 436 idx2 = ((((size_t)(data[2 * i])) & 3) + 437 (seed / 6)) % 6; 438 retval[j++] = vowels[idx0]; 439 retval[j++] = consonants[idx1]; 440 retval[j++] = vowels[idx2]; 441 if ((i + 1) < rounds) { 442 idx3 = (((size_t)(data[(2 * i) + 1])) >> 4) & 15; 443 idx4 = (((size_t)(data[(2 * i) + 1]))) & 15; 444 retval[j++] = consonants[idx3]; 445 retval[j++] = '-'; 446 retval[j++] = consonants[idx4]; 447 seed = ((seed * 5) + 448 ((((size_t)(data[2 * i])) * 7) + 449 ((size_t)(data[(2 * i) + 1])))) % 36; 450 } 451 } else { 452 idx0 = seed % 6; 453 idx1 = 16; 454 idx2 = seed / 6; 455 retval[j++] = vowels[idx0]; 456 retval[j++] = consonants[idx1]; 457 retval[j++] = vowels[idx2]; 458 } 459 } 460 retval[j++] = 'x'; 461 retval[j++] = '\0'; 462 return retval; 463 } 464 465 /* 466 * For backwards compatibility, because we have always exported this symbol. 467 */ 468 #ifdef HAVE_B64_NTOP 469 int ldns_b64_ntop(const uint8_t* src, size_t srclength, 470 char *target, size_t targsize); 471 { 472 return b64_ntop(src, srclength, target, targsize); 473 } 474 #endif 475 476 /* 477 * For backwards compatibility, because we have always exported this symbol. 478 */ 479 #ifdef HAVE_B64_PTON 480 int ldns_b64_pton(const char* src, uint8_t *target, size_t targsize) 481 { 482 return b64_pton(src, target, targsize); 483 } 484 #endif 485 486 487 static int 488 ldns_b32_ntop_base(const uint8_t* src, size_t src_sz, 489 char* dst, size_t dst_sz, 490 bool extended_hex, bool add_padding) 491 { 492 size_t ret_sz; 493 const char* b32 = extended_hex ? "0123456789abcdefghijklmnopqrstuv" 494 : "abcdefghijklmnopqrstuvwxyz234567"; 495 496 size_t c = 0; /* c is used to carry partial base32 character over 497 * byte boundaries for sizes with a remainder. 498 * (i.e. src_sz % 5 != 0) 499 */ 500 501 ret_sz = add_padding ? ldns_b32_ntop_calculate_size(src_sz) 502 : ldns_b32_ntop_calculate_size_no_padding(src_sz); 503 504 /* Do we have enough space? */ 505 if (dst_sz < ret_sz + 1) 506 return -1; 507 508 /* We know the size; terminate the string */ 509 dst[ret_sz] = '\0'; 510 511 /* First process all chunks of five */ 512 while (src_sz >= 5) { 513 /* 00000... ........ ........ ........ ........ */ 514 dst[0] = b32[(src[0] ) >> 3]; 515 516 /* .....111 11...... ........ ........ ........ */ 517 dst[1] = b32[(src[0] & 0x07) << 2 | src[1] >> 6]; 518 519 /* ........ ..22222. ........ ........ ........ */ 520 dst[2] = b32[(src[1] & 0x3e) >> 1]; 521 522 /* ........ .......3 3333.... ........ ........ */ 523 dst[3] = b32[(src[1] & 0x01) << 4 | src[2] >> 4]; 524 525 /* ........ ........ ....4444 4....... ........ */ 526 dst[4] = b32[(src[2] & 0x0f) << 1 | src[3] >> 7]; 527 528 /* ........ ........ ........ .55555.. ........ */ 529 dst[5] = b32[(src[3] & 0x7c) >> 2]; 530 531 /* ........ ........ ........ ......66 666..... */ 532 dst[6] = b32[(src[3] & 0x03) << 3 | src[4] >> 5]; 533 534 /* ........ ........ ........ ........ ...77777 */ 535 dst[7] = b32[(src[4] & 0x1f) ]; 536 537 src_sz -= 5; 538 src += 5; 539 dst += 8; 540 } 541 /* Process what remains */ 542 switch (src_sz) { 543 case 4: /* ........ ........ ........ ......66 666..... */ 544 dst[6] = b32[(src[3] & 0x03) << 3]; 545 546 /* ........ ........ ........ .55555.. ........ */ 547 dst[5] = b32[(src[3] & 0x7c) >> 2]; 548 549 /* ........ ........ ....4444 4....... ........ */ 550 c = src[3] >> 7 ; 551 case 3: dst[4] = b32[(src[2] & 0x0f) << 1 | c]; 552 553 /* ........ .......3 3333.... ........ ........ */ 554 c = src[2] >> 4 ; 555 case 2: dst[3] = b32[(src[1] & 0x01) << 4 | c]; 556 557 /* ........ ..22222. ........ ........ ........ */ 558 dst[2] = b32[(src[1] & 0x3e) >> 1]; 559 560 /* .....111 11...... ........ ........ ........ */ 561 c = src[1] >> 6 ; 562 case 1: dst[1] = b32[(src[0] & 0x07) << 2 | c]; 563 564 /* 00000... ........ ........ ........ ........ */ 565 dst[0] = b32[ src[0] >> 3]; 566 } 567 /* Add padding */ 568 if (add_padding) { 569 switch (src_sz) { 570 case 1: dst[2] = '='; 571 dst[3] = '='; 572 case 2: dst[4] = '='; 573 case 3: dst[5] = '='; 574 dst[6] = '='; 575 case 4: dst[7] = '='; 576 } 577 } 578 return (int)ret_sz; 579 } 580 581 int 582 ldns_b32_ntop(const uint8_t* src, size_t src_sz, char* dst, size_t dst_sz) 583 { 584 return ldns_b32_ntop_base(src, src_sz, dst, dst_sz, false, true); 585 } 586 587 int 588 ldns_b32_ntop_extended_hex(const uint8_t* src, size_t src_sz, 589 char* dst, size_t dst_sz) 590 { 591 return ldns_b32_ntop_base(src, src_sz, dst, dst_sz, true, true); 592 } 593 594 #ifndef HAVE_B32_NTOP 595 596 int 597 b32_ntop(const uint8_t* src, size_t src_sz, char* dst, size_t dst_sz) 598 { 599 return ldns_b32_ntop_base(src, src_sz, dst, dst_sz, false, true); 600 } 601 602 int 603 b32_ntop_extended_hex(const uint8_t* src, size_t src_sz, 604 char* dst, size_t dst_sz) 605 { 606 return ldns_b32_ntop_base(src, src_sz, dst, dst_sz, true, true); 607 } 608 609 #endif /* ! HAVE_B32_NTOP */ 610 611 static int 612 ldns_b32_pton_base(const char* src, size_t src_sz, 613 uint8_t* dst, size_t dst_sz, 614 bool extended_hex, bool check_padding) 615 { 616 size_t i = 0; 617 char ch = '\0'; 618 uint8_t buf[8]; 619 uint8_t* start = dst; 620 621 while (src_sz) { 622 /* Collect 8 characters in buf (if possible) */ 623 for (i = 0; i < 8; i++) { 624 625 do { 626 ch = *src++; 627 --src_sz; 628 629 } while (isspace(ch) && src_sz > 0); 630 631 if (ch == '=' || ch == '\0') 632 break; 633 634 else if (extended_hex) 635 636 if (ch >= '0' && ch <= '9') 637 buf[i] = (uint8_t)ch - '0'; 638 else if (ch >= 'a' && ch <= 'v') 639 buf[i] = (uint8_t)ch - 'a' + 10; 640 else if (ch >= 'A' && ch <= 'V') 641 buf[i] = (uint8_t)ch - 'A' + 10; 642 else 643 return -1; 644 645 else if (ch >= 'a' && ch <= 'z') 646 buf[i] = (uint8_t)ch - 'a'; 647 else if (ch >= 'A' && ch <= 'Z') 648 buf[i] = (uint8_t)ch - 'A'; 649 else if (ch >= '2' && ch <= '7') 650 buf[i] = (uint8_t)ch - '2' + 26; 651 else 652 return -1; 653 } 654 /* Less that 8 characters. We're done. */ 655 if (i < 8) 656 break; 657 658 /* Enough space available at the destination? */ 659 if (dst_sz < 5) 660 return -1; 661 662 /* 00000... ........ ........ ........ ........ */ 663 /* .....111 11...... ........ ........ ........ */ 664 dst[0] = buf[0] << 3 | buf[1] >> 2; 665 666 /* .....111 11...... ........ ........ ........ */ 667 /* ........ ..22222. ........ ........ ........ */ 668 /* ........ .......3 3333.... ........ ........ */ 669 dst[1] = buf[1] << 6 | buf[2] << 1 | buf[3] >> 4; 670 671 /* ........ .......3 3333.... ........ ........ */ 672 /* ........ ........ ....4444 4....... ........ */ 673 dst[2] = buf[3] << 4 | buf[4] >> 1; 674 675 /* ........ ........ ....4444 4....... ........ */ 676 /* ........ ........ ........ .55555.. ........ */ 677 /* ........ ........ ........ ......66 666..... */ 678 dst[3] = buf[4] << 7 | buf[5] << 2 | buf[6] >> 3; 679 680 /* ........ ........ ........ ......66 666..... */ 681 /* ........ ........ ........ ........ ...77777 */ 682 dst[4] = buf[6] << 5 | buf[7]; 683 684 dst += 5; 685 dst_sz -= 5; 686 } 687 /* Not ending on a eight byte boundary? */ 688 if (i > 0 && i < 8) { 689 690 /* Enough space available at the destination? */ 691 if (dst_sz < (i + 1) / 2) 692 return -1; 693 694 switch (i) { 695 case 7: /* ........ ........ ........ ......66 666..... */ 696 /* ........ ........ ........ .55555.. ........ */ 697 /* ........ ........ ....4444 4....... ........ */ 698 dst[3] = buf[4] << 7 | buf[5] << 2 | buf[6] >> 3; 699 700 case 5: /* ........ ........ ....4444 4....... ........ */ 701 /* ........ .......3 3333.... ........ ........ */ 702 dst[2] = buf[3] << 4 | buf[4] >> 1; 703 704 case 4: /* ........ .......3 3333.... ........ ........ */ 705 /* ........ ..22222. ........ ........ ........ */ 706 /* .....111 11...... ........ ........ ........ */ 707 dst[1] = buf[1] << 6 | buf[2] << 1 | buf[3] >> 4; 708 709 case 2: /* .....111 11...... ........ ........ ........ */ 710 /* 00000... ........ ........ ........ ........ */ 711 dst[0] = buf[0] << 3 | buf[1] >> 2; 712 713 break; 714 715 default: 716 return -1; 717 } 718 dst += (i + 1) / 2; 719 720 if (check_padding) { 721 /* Check remaining padding characters */ 722 if (ch != '=') 723 return -1; 724 725 /* One down, 8 - i - 1 more to come... */ 726 for (i = 8 - i - 1; i > 0; i--) { 727 728 do { 729 if (src_sz == 0) 730 return -1; 731 ch = *src++; 732 src_sz--; 733 734 } while (isspace(ch)); 735 736 if (ch != '=') 737 return -1; 738 } 739 } 740 } 741 return dst - start; 742 } 743 744 int 745 ldns_b32_pton(const char* src, size_t src_sz, uint8_t* dst, size_t dst_sz) 746 { 747 return ldns_b32_pton_base(src, src_sz, dst, dst_sz, false, true); 748 } 749 750 int 751 ldns_b32_pton_extended_hex(const char* src, size_t src_sz, 752 uint8_t* dst, size_t dst_sz) 753 { 754 return ldns_b32_pton_base(src, src_sz, dst, dst_sz, true, true); 755 } 756 757 #ifndef HAVE_B32_PTON 758 759 int 760 b32_pton(const char* src, size_t src_sz, uint8_t* dst, size_t dst_sz) 761 { 762 return ldns_b32_pton_base(src, src_sz, dst, dst_sz, false, true); 763 } 764 765 int 766 b32_pton_extended_hex(const char* src, size_t src_sz, 767 uint8_t* dst, size_t dst_sz) 768 { 769 return ldns_b32_pton_base(src, src_sz, dst, dst_sz, true, true); 770 } 771 772 #endif /* ! HAVE_B32_PTON */ 773 774