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_arithmetics_time(int32_t time, time_t now) 297 { 298 /* Casting due to https://github.com/NLnetLabs/ldns/issues/71 */ 299 int32_t offset = (int32_t) ((uint32_t) time - (uint32_t) now); 300 return (int64_t) now + offset; 301 } 302 303 struct tm * 304 ldns_serial_arithmetics_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_arithmetics_time(time, now); 308 return ldns_gmtime64_r(secs_since_epoch, result); 309 #else 310 time_t secs_since_epoch = ldns_serial_arithmetics_time(time, now); 311 return gmtime_r(&secs_since_epoch, result); 312 #endif 313 } 314 315 #ifdef ldns_serial_arithmitics_gmtime_r 316 #undef ldns_serial_arithmitics_gmtime_r 317 #endif 318 /* alias function because of previously used wrong spelling */ 319 struct tm * 320 ldns_serial_arithmitics_gmtime_r(int32_t time, time_t now, struct tm *result) 321 { 322 return ldns_serial_arithmetics_gmtime_r(time, now, result); 323 } 324 325 /** 326 * Init the random source 327 * applications should call this if they need entropy data within ldns 328 * If openSSL is available, it is automatically seeded from /dev/urandom 329 * or /dev/random 330 * 331 * If you need more entropy, or have no openssl available, this function 332 * MUST be called at the start of the program 333 * 334 * If openssl *is* available, this function just adds more entropy 335 **/ 336 int 337 ldns_init_random(FILE *fd, unsigned int size) 338 { 339 /* if fp is given, seed srandom with data from file 340 otherwise use /dev/urandom */ 341 FILE *rand_f; 342 uint8_t *seed; 343 size_t read = 0; 344 unsigned int seed_i; 345 struct timeval tv; 346 347 /* we'll need at least sizeof(unsigned int) bytes for the 348 standard prng seed */ 349 if (size < (unsigned int) sizeof(seed_i)){ 350 size = (unsigned int) sizeof(seed_i); 351 } 352 353 seed = LDNS_XMALLOC(uint8_t, size); 354 if(!seed) { 355 return 1; 356 } 357 358 if (!fd) { 359 if ((rand_f = fopen("/dev/urandom", "r")) == NULL) { 360 /* no readable /dev/urandom, try /dev/random */ 361 if ((rand_f = fopen("/dev/random", "r")) == NULL) { 362 /* no readable /dev/random either, and no entropy 363 source given. we'll have to improvise */ 364 for (read = 0; read < size; read++) { 365 gettimeofday(&tv, NULL); 366 seed[read] = (uint8_t) (tv.tv_usec % 256); 367 } 368 } else { 369 read = fread(seed, 1, size, rand_f); 370 } 371 } else { 372 read = fread(seed, 1, size, rand_f); 373 } 374 } else { 375 rand_f = fd; 376 read = fread(seed, 1, size, rand_f); 377 } 378 379 if (read < size) { 380 LDNS_FREE(seed); 381 if (!fd) fclose(rand_f); 382 return 1; 383 } else { 384 #ifdef HAVE_SSL 385 /* Seed the OpenSSL prng (most systems have it seeded 386 automatically, in that case this call just adds entropy */ 387 RAND_seed(seed, (int) size); 388 #else 389 /* Seed the standard prng, only uses the first 390 * unsigned sizeof(unsigned int) bytes found in the entropy pool 391 */ 392 memcpy(&seed_i, seed, sizeof(seed_i)); 393 srandom(seed_i); 394 #endif 395 LDNS_FREE(seed); 396 } 397 398 if (!fd) { 399 if (rand_f) fclose(rand_f); 400 } 401 402 return 0; 403 } 404 405 /** 406 * Get random number. 407 * 408 */ 409 uint16_t 410 ldns_get_random(void) 411 { 412 uint16_t rid = 0; 413 #ifdef HAVE_SSL 414 if (RAND_bytes((unsigned char*)&rid, 2) != 1) { 415 rid = (uint16_t) random(); 416 } 417 #else 418 rid = (uint16_t) random(); 419 #endif 420 return rid; 421 } 422 423 /* 424 * BubbleBabble code taken from OpenSSH 425 * Copyright (c) 2001 Carsten Raskgaard. All rights reserved. 426 */ 427 char * 428 ldns_bubblebabble(uint8_t *data, size_t len) 429 { 430 char vowels[] = { 'a', 'e', 'i', 'o', 'u', 'y' }; 431 char consonants[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm', 432 'n', 'p', 'r', 's', 't', 'v', 'z', 'x' }; 433 size_t i, j = 0, rounds, seed = 1; 434 char *retval; 435 436 rounds = (len / 2) + 1; 437 retval = LDNS_XMALLOC(char, rounds * 6); 438 if(!retval) return NULL; 439 retval[j++] = 'x'; 440 for (i = 0; i < rounds; i++) { 441 size_t idx0, idx1, idx2, idx3, idx4; 442 if ((i + 1 < rounds) || (len % 2 != 0)) { 443 idx0 = (((((size_t)(data[2 * i])) >> 6) & 3) + 444 seed) % 6; 445 idx1 = (((size_t)(data[2 * i])) >> 2) & 15; 446 idx2 = ((((size_t)(data[2 * i])) & 3) + 447 (seed / 6)) % 6; 448 retval[j++] = vowels[idx0]; 449 retval[j++] = consonants[idx1]; 450 retval[j++] = vowels[idx2]; 451 if ((i + 1) < rounds) { 452 idx3 = (((size_t)(data[(2 * i) + 1])) >> 4) & 15; 453 idx4 = (((size_t)(data[(2 * i) + 1]))) & 15; 454 retval[j++] = consonants[idx3]; 455 retval[j++] = '-'; 456 retval[j++] = consonants[idx4]; 457 seed = ((seed * 5) + 458 ((((size_t)(data[2 * i])) * 7) + 459 ((size_t)(data[(2 * i) + 1])))) % 36; 460 } 461 } else { 462 idx0 = seed % 6; 463 idx1 = 16; 464 idx2 = seed / 6; 465 retval[j++] = vowels[idx0]; 466 retval[j++] = consonants[idx1]; 467 retval[j++] = vowels[idx2]; 468 } 469 } 470 retval[j++] = 'x'; 471 retval[j++] = '\0'; 472 return retval; 473 } 474 475 /* 476 * For backwards compatibility, because we have always exported this symbol. 477 */ 478 #ifdef HAVE_B64_NTOP 479 int ldns_b64_ntop(const uint8_t* src, size_t srclength, 480 char *target, size_t targsize); 481 { 482 return b64_ntop(src, srclength, target, targsize); 483 } 484 #endif 485 486 /* 487 * For backwards compatibility, because we have always exported this symbol. 488 */ 489 #ifdef HAVE_B64_PTON 490 int ldns_b64_pton(const char* src, uint8_t *target, size_t targsize) 491 { 492 return b64_pton(src, target, targsize); 493 } 494 #endif 495 496 497 static int 498 ldns_b32_ntop_base(const uint8_t* src, size_t src_sz, 499 char* dst, size_t dst_sz, 500 bool extended_hex, bool add_padding) 501 { 502 size_t ret_sz; 503 const char* b32 = extended_hex ? "0123456789abcdefghijklmnopqrstuv" 504 : "abcdefghijklmnopqrstuvwxyz234567"; 505 506 size_t c = 0; /* c is used to carry partial base32 character over 507 * byte boundaries for sizes with a remainder. 508 * (i.e. src_sz % 5 != 0) 509 */ 510 511 ret_sz = add_padding ? ldns_b32_ntop_calculate_size(src_sz) 512 : ldns_b32_ntop_calculate_size_no_padding(src_sz); 513 514 /* Do we have enough space? */ 515 if (dst_sz < ret_sz + 1) 516 return -1; 517 518 /* We know the size; terminate the string */ 519 dst[ret_sz] = '\0'; 520 521 /* First process all chunks of five */ 522 while (src_sz >= 5) { 523 /* 00000... ........ ........ ........ ........ */ 524 dst[0] = b32[(src[0] ) >> 3]; 525 526 /* .....111 11...... ........ ........ ........ */ 527 dst[1] = b32[(src[0] & 0x07) << 2 | src[1] >> 6]; 528 529 /* ........ ..22222. ........ ........ ........ */ 530 dst[2] = b32[(src[1] & 0x3e) >> 1]; 531 532 /* ........ .......3 3333.... ........ ........ */ 533 dst[3] = b32[(src[1] & 0x01) << 4 | src[2] >> 4]; 534 535 /* ........ ........ ....4444 4....... ........ */ 536 dst[4] = b32[(src[2] & 0x0f) << 1 | src[3] >> 7]; 537 538 /* ........ ........ ........ .55555.. ........ */ 539 dst[5] = b32[(src[3] & 0x7c) >> 2]; 540 541 /* ........ ........ ........ ......66 666..... */ 542 dst[6] = b32[(src[3] & 0x03) << 3 | src[4] >> 5]; 543 544 /* ........ ........ ........ ........ ...77777 */ 545 dst[7] = b32[(src[4] & 0x1f) ]; 546 547 src_sz -= 5; 548 src += 5; 549 dst += 8; 550 } 551 /* Process what remains */ 552 switch (src_sz) { 553 case 4: /* ........ ........ ........ ......66 666..... */ 554 dst[6] = b32[(src[3] & 0x03) << 3]; 555 556 /* ........ ........ ........ .55555.. ........ */ 557 dst[5] = b32[(src[3] & 0x7c) >> 2]; 558 559 /* ........ ........ ....4444 4....... ........ */ 560 c = src[3] >> 7 ; 561 /* fallthrough */ 562 case 3: dst[4] = b32[(src[2] & 0x0f) << 1 | c]; 563 564 /* ........ .......3 3333.... ........ ........ */ 565 c = src[2] >> 4 ; 566 /* fallthrough */ 567 case 2: dst[3] = b32[(src[1] & 0x01) << 4 | c]; 568 569 /* ........ ..22222. ........ ........ ........ */ 570 dst[2] = b32[(src[1] & 0x3e) >> 1]; 571 572 /* .....111 11...... ........ ........ ........ */ 573 c = src[1] >> 6 ; 574 /* fallthrough */ 575 case 1: dst[1] = b32[(src[0] & 0x07) << 2 | c]; 576 577 /* 00000... ........ ........ ........ ........ */ 578 dst[0] = b32[ src[0] >> 3]; 579 } 580 /* Add padding */ 581 if (add_padding) { 582 switch (src_sz) { 583 case 1: dst[2] = '='; 584 dst[3] = '='; 585 /* fallthrough */ 586 case 2: dst[4] = '='; 587 /* fallthrough */ 588 case 3: dst[5] = '='; 589 dst[6] = '='; 590 /* fallthrough */ 591 case 4: dst[7] = '='; 592 } 593 } 594 return (int)ret_sz; 595 } 596 597 int 598 ldns_b32_ntop(const uint8_t* src, size_t src_sz, char* dst, size_t dst_sz) 599 { 600 return ldns_b32_ntop_base(src, src_sz, dst, dst_sz, false, true); 601 } 602 603 int 604 ldns_b32_ntop_extended_hex(const uint8_t* src, size_t src_sz, 605 char* dst, size_t dst_sz) 606 { 607 return ldns_b32_ntop_base(src, src_sz, dst, dst_sz, true, true); 608 } 609 610 #ifndef HAVE_B32_NTOP 611 612 int 613 b32_ntop(const uint8_t* src, size_t src_sz, char* dst, size_t dst_sz) 614 { 615 return ldns_b32_ntop_base(src, src_sz, dst, dst_sz, false, true); 616 } 617 618 int 619 b32_ntop_extended_hex(const uint8_t* src, size_t src_sz, 620 char* dst, size_t dst_sz) 621 { 622 return ldns_b32_ntop_base(src, src_sz, dst, dst_sz, true, true); 623 } 624 625 #endif /* ! HAVE_B32_NTOP */ 626 627 static int 628 ldns_b32_pton_base(const char* src, size_t src_sz, 629 uint8_t* dst, size_t dst_sz, 630 bool extended_hex, bool check_padding) 631 { 632 size_t i = 0; 633 char ch = '\0'; 634 uint8_t buf[8]; 635 uint8_t* start = dst; 636 637 while (src_sz) { 638 /* Collect 8 characters in buf (if possible) */ 639 for (i = 0; i < 8; i++) { 640 641 do { 642 ch = *src++; 643 --src_sz; 644 645 } while (isspace((unsigned char)ch) && src_sz > 0); 646 647 if (ch == '=' || ch == '\0') 648 break; 649 650 else if (extended_hex) 651 652 if (ch >= '0' && ch <= '9') 653 buf[i] = (uint8_t)ch - '0'; 654 else if (ch >= 'a' && ch <= 'v') 655 buf[i] = (uint8_t)ch - 'a' + 10; 656 else if (ch >= 'A' && ch <= 'V') 657 buf[i] = (uint8_t)ch - 'A' + 10; 658 else 659 return -1; 660 661 else if (ch >= 'a' && ch <= 'z') 662 buf[i] = (uint8_t)ch - 'a'; 663 else if (ch >= 'A' && ch <= 'Z') 664 buf[i] = (uint8_t)ch - 'A'; 665 else if (ch >= '2' && ch <= '7') 666 buf[i] = (uint8_t)ch - '2' + 26; 667 else 668 return -1; 669 } 670 /* Less that 8 characters. We're done. */ 671 if (i < 8) 672 break; 673 674 /* Enough space available at the destination? */ 675 if (dst_sz < 5) 676 return -1; 677 678 /* 00000... ........ ........ ........ ........ */ 679 /* .....111 11...... ........ ........ ........ */ 680 dst[0] = buf[0] << 3 | buf[1] >> 2; 681 682 /* .....111 11...... ........ ........ ........ */ 683 /* ........ ..22222. ........ ........ ........ */ 684 /* ........ .......3 3333.... ........ ........ */ 685 dst[1] = buf[1] << 6 | buf[2] << 1 | buf[3] >> 4; 686 687 /* ........ .......3 3333.... ........ ........ */ 688 /* ........ ........ ....4444 4....... ........ */ 689 dst[2] = buf[3] << 4 | buf[4] >> 1; 690 691 /* ........ ........ ....4444 4....... ........ */ 692 /* ........ ........ ........ .55555.. ........ */ 693 /* ........ ........ ........ ......66 666..... */ 694 dst[3] = buf[4] << 7 | buf[5] << 2 | buf[6] >> 3; 695 696 /* ........ ........ ........ ......66 666..... */ 697 /* ........ ........ ........ ........ ...77777 */ 698 dst[4] = buf[6] << 5 | buf[7]; 699 700 dst += 5; 701 dst_sz -= 5; 702 } 703 /* Not ending on a eight byte boundary? */ 704 if (i > 0 && i < 8) { 705 706 /* Enough space available at the destination? */ 707 if (dst_sz < (i + 1) / 2) 708 return -1; 709 710 switch (i) { 711 case 7: /* ........ ........ ........ ......66 666..... */ 712 /* ........ ........ ........ .55555.. ........ */ 713 /* ........ ........ ....4444 4....... ........ */ 714 dst[3] = buf[4] << 7 | buf[5] << 2 | buf[6] >> 3; 715 /* fallthrough */ 716 717 case 5: /* ........ ........ ....4444 4....... ........ */ 718 /* ........ .......3 3333.... ........ ........ */ 719 dst[2] = buf[3] << 4 | buf[4] >> 1; 720 /* fallthrough */ 721 722 case 4: /* ........ .......3 3333.... ........ ........ */ 723 /* ........ ..22222. ........ ........ ........ */ 724 /* .....111 11...... ........ ........ ........ */ 725 dst[1] = buf[1] << 6 | buf[2] << 1 | buf[3] >> 4; 726 /* fallthrough */ 727 728 case 2: /* .....111 11...... ........ ........ ........ */ 729 /* 00000... ........ ........ ........ ........ */ 730 dst[0] = buf[0] << 3 | buf[1] >> 2; 731 732 break; 733 734 default: 735 return -1; 736 } 737 dst += (i + 1) / 2; 738 739 if (check_padding) { 740 /* Check remaining padding characters */ 741 if (ch != '=') 742 return -1; 743 744 /* One down, 8 - i - 1 more to come... */ 745 for (i = 8 - i - 1; i > 0; i--) { 746 747 do { 748 if (src_sz == 0) 749 return -1; 750 ch = *src++; 751 src_sz--; 752 753 } while (isspace((unsigned char)ch)); 754 755 if (ch != '=') 756 return -1; 757 } 758 } 759 } 760 return dst - start; 761 } 762 763 int 764 ldns_b32_pton(const char* src, size_t src_sz, uint8_t* dst, size_t dst_sz) 765 { 766 return ldns_b32_pton_base(src, src_sz, dst, dst_sz, false, true); 767 } 768 769 int 770 ldns_b32_pton_extended_hex(const char* src, size_t src_sz, 771 uint8_t* dst, size_t dst_sz) 772 { 773 return ldns_b32_pton_base(src, src_sz, dst, dst_sz, true, true); 774 } 775 776 #ifndef HAVE_B32_PTON 777 778 int 779 b32_pton(const char* src, size_t src_sz, uint8_t* dst, size_t dst_sz) 780 { 781 return ldns_b32_pton_base(src, src_sz, dst, dst_sz, false, true); 782 } 783 784 int 785 b32_pton_extended_hex(const char* src, size_t src_sz, 786 uint8_t* dst, size_t dst_sz) 787 { 788 return ldns_b32_pton_base(src, src_sz, dst, dst_sz, true, true); 789 } 790 791 #endif /* ! HAVE_B32_PTON */ 792 793