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