17b5038d7SDag-Erling Smørgrav /* 27b5038d7SDag-Erling Smørgrav * util.c 37b5038d7SDag-Erling Smørgrav * 47b5038d7SDag-Erling Smørgrav * some general memory functions 57b5038d7SDag-Erling Smørgrav * 67b5038d7SDag-Erling Smørgrav * a Net::DNS like library for C 77b5038d7SDag-Erling Smørgrav * 87b5038d7SDag-Erling Smørgrav * (c) NLnet Labs, 2004-2006 97b5038d7SDag-Erling Smørgrav * 107b5038d7SDag-Erling Smørgrav * See the file LICENSE for the license 117b5038d7SDag-Erling Smørgrav */ 127b5038d7SDag-Erling Smørgrav 137b5038d7SDag-Erling Smørgrav #include <ldns/config.h> 147b5038d7SDag-Erling Smørgrav 157b5038d7SDag-Erling Smørgrav #include <ldns/rdata.h> 167b5038d7SDag-Erling Smørgrav #include <ldns/rr.h> 177b5038d7SDag-Erling Smørgrav #include <ldns/util.h> 187b5038d7SDag-Erling Smørgrav #include <strings.h> 197b5038d7SDag-Erling Smørgrav #include <stdlib.h> 207b5038d7SDag-Erling Smørgrav #include <stdio.h> 217b5038d7SDag-Erling Smørgrav #include <sys/time.h> 227b5038d7SDag-Erling Smørgrav #include <time.h> 23*17d15b25SDag-Erling Smørgrav #include <ctype.h> 247b5038d7SDag-Erling Smørgrav 257b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL 267b5038d7SDag-Erling Smørgrav #include <openssl/rand.h> 277b5038d7SDag-Erling Smørgrav #endif 287b5038d7SDag-Erling Smørgrav 297b5038d7SDag-Erling Smørgrav ldns_lookup_table * 307b5038d7SDag-Erling Smørgrav ldns_lookup_by_name(ldns_lookup_table *table, const char *name) 317b5038d7SDag-Erling Smørgrav { 327b5038d7SDag-Erling Smørgrav while (table->name != NULL) { 337b5038d7SDag-Erling Smørgrav if (strcasecmp(name, table->name) == 0) 347b5038d7SDag-Erling Smørgrav return table; 357b5038d7SDag-Erling Smørgrav table++; 367b5038d7SDag-Erling Smørgrav } 377b5038d7SDag-Erling Smørgrav return NULL; 387b5038d7SDag-Erling Smørgrav } 397b5038d7SDag-Erling Smørgrav 407b5038d7SDag-Erling Smørgrav ldns_lookup_table * 417b5038d7SDag-Erling Smørgrav ldns_lookup_by_id(ldns_lookup_table *table, int id) 427b5038d7SDag-Erling Smørgrav { 437b5038d7SDag-Erling Smørgrav while (table->name != NULL) { 447b5038d7SDag-Erling Smørgrav if (table->id == id) 457b5038d7SDag-Erling Smørgrav return table; 467b5038d7SDag-Erling Smørgrav table++; 477b5038d7SDag-Erling Smørgrav } 487b5038d7SDag-Erling Smørgrav return NULL; 497b5038d7SDag-Erling Smørgrav } 507b5038d7SDag-Erling Smørgrav 517b5038d7SDag-Erling Smørgrav int 527b5038d7SDag-Erling Smørgrav ldns_get_bit(uint8_t bits[], size_t index) 537b5038d7SDag-Erling Smørgrav { 547b5038d7SDag-Erling Smørgrav /* 557b5038d7SDag-Erling Smørgrav * The bits are counted from left to right, so bit #0 is the 567b5038d7SDag-Erling Smørgrav * left most bit. 577b5038d7SDag-Erling Smørgrav */ 587b5038d7SDag-Erling Smørgrav return (int) (bits[index / 8] & (1 << (7 - index % 8))); 597b5038d7SDag-Erling Smørgrav } 607b5038d7SDag-Erling Smørgrav 617b5038d7SDag-Erling Smørgrav int 627b5038d7SDag-Erling Smørgrav ldns_get_bit_r(uint8_t bits[], size_t index) 637b5038d7SDag-Erling Smørgrav { 647b5038d7SDag-Erling Smørgrav /* 657b5038d7SDag-Erling Smørgrav * The bits are counted from right to left, so bit #0 is the 667b5038d7SDag-Erling Smørgrav * right most bit. 677b5038d7SDag-Erling Smørgrav */ 687b5038d7SDag-Erling Smørgrav return (int) bits[index / 8] & (1 << (index % 8)); 697b5038d7SDag-Erling Smørgrav } 707b5038d7SDag-Erling Smørgrav 717b5038d7SDag-Erling Smørgrav void 727b5038d7SDag-Erling Smørgrav ldns_set_bit(uint8_t *byte, int bit_nr, bool value) 737b5038d7SDag-Erling Smørgrav { 747b5038d7SDag-Erling Smørgrav /* 757b5038d7SDag-Erling Smørgrav * The bits are counted from right to left, so bit #0 is the 767b5038d7SDag-Erling Smørgrav * right most bit. 777b5038d7SDag-Erling Smørgrav */ 787b5038d7SDag-Erling Smørgrav if (bit_nr >= 0 && bit_nr < 8) { 797b5038d7SDag-Erling Smørgrav if (value) { 807b5038d7SDag-Erling Smørgrav *byte = *byte | (0x01 << bit_nr); 817b5038d7SDag-Erling Smørgrav } else { 827b5038d7SDag-Erling Smørgrav *byte = *byte & ~(0x01 << bit_nr); 837b5038d7SDag-Erling Smørgrav } 847b5038d7SDag-Erling Smørgrav } 857b5038d7SDag-Erling Smørgrav } 867b5038d7SDag-Erling Smørgrav 877b5038d7SDag-Erling Smørgrav int 887b5038d7SDag-Erling Smørgrav ldns_hexdigit_to_int(char ch) 897b5038d7SDag-Erling Smørgrav { 907b5038d7SDag-Erling Smørgrav switch (ch) { 917b5038d7SDag-Erling Smørgrav case '0': return 0; 927b5038d7SDag-Erling Smørgrav case '1': return 1; 937b5038d7SDag-Erling Smørgrav case '2': return 2; 947b5038d7SDag-Erling Smørgrav case '3': return 3; 957b5038d7SDag-Erling Smørgrav case '4': return 4; 967b5038d7SDag-Erling Smørgrav case '5': return 5; 977b5038d7SDag-Erling Smørgrav case '6': return 6; 987b5038d7SDag-Erling Smørgrav case '7': return 7; 997b5038d7SDag-Erling Smørgrav case '8': return 8; 1007b5038d7SDag-Erling Smørgrav case '9': return 9; 1017b5038d7SDag-Erling Smørgrav case 'a': case 'A': return 10; 1027b5038d7SDag-Erling Smørgrav case 'b': case 'B': return 11; 1037b5038d7SDag-Erling Smørgrav case 'c': case 'C': return 12; 1047b5038d7SDag-Erling Smørgrav case 'd': case 'D': return 13; 1057b5038d7SDag-Erling Smørgrav case 'e': case 'E': return 14; 1067b5038d7SDag-Erling Smørgrav case 'f': case 'F': return 15; 1077b5038d7SDag-Erling Smørgrav default: 1087b5038d7SDag-Erling Smørgrav return -1; 1097b5038d7SDag-Erling Smørgrav } 1107b5038d7SDag-Erling Smørgrav } 1117b5038d7SDag-Erling Smørgrav 1127b5038d7SDag-Erling Smørgrav char 1137b5038d7SDag-Erling Smørgrav ldns_int_to_hexdigit(int i) 1147b5038d7SDag-Erling Smørgrav { 1157b5038d7SDag-Erling Smørgrav switch (i) { 1167b5038d7SDag-Erling Smørgrav case 0: return '0'; 1177b5038d7SDag-Erling Smørgrav case 1: return '1'; 1187b5038d7SDag-Erling Smørgrav case 2: return '2'; 1197b5038d7SDag-Erling Smørgrav case 3: return '3'; 1207b5038d7SDag-Erling Smørgrav case 4: return '4'; 1217b5038d7SDag-Erling Smørgrav case 5: return '5'; 1227b5038d7SDag-Erling Smørgrav case 6: return '6'; 1237b5038d7SDag-Erling Smørgrav case 7: return '7'; 1247b5038d7SDag-Erling Smørgrav case 8: return '8'; 1257b5038d7SDag-Erling Smørgrav case 9: return '9'; 1267b5038d7SDag-Erling Smørgrav case 10: return 'a'; 1277b5038d7SDag-Erling Smørgrav case 11: return 'b'; 1287b5038d7SDag-Erling Smørgrav case 12: return 'c'; 1297b5038d7SDag-Erling Smørgrav case 13: return 'd'; 1307b5038d7SDag-Erling Smørgrav case 14: return 'e'; 1317b5038d7SDag-Erling Smørgrav case 15: return 'f'; 1327b5038d7SDag-Erling Smørgrav default: 1337b5038d7SDag-Erling Smørgrav abort(); 1347b5038d7SDag-Erling Smørgrav } 1357b5038d7SDag-Erling Smørgrav } 1367b5038d7SDag-Erling Smørgrav 1377b5038d7SDag-Erling Smørgrav int 1387b5038d7SDag-Erling Smørgrav ldns_hexstring_to_data(uint8_t *data, const char *str) 1397b5038d7SDag-Erling Smørgrav { 1407b5038d7SDag-Erling Smørgrav size_t i; 1417b5038d7SDag-Erling Smørgrav 1427b5038d7SDag-Erling Smørgrav if (!str || !data) { 1437b5038d7SDag-Erling Smørgrav return -1; 1447b5038d7SDag-Erling Smørgrav } 1457b5038d7SDag-Erling Smørgrav 1467b5038d7SDag-Erling Smørgrav if (strlen(str) % 2 != 0) { 1477b5038d7SDag-Erling Smørgrav return -2; 1487b5038d7SDag-Erling Smørgrav } 1497b5038d7SDag-Erling Smørgrav 1507b5038d7SDag-Erling Smørgrav for (i = 0; i < strlen(str) / 2; i++) { 1517b5038d7SDag-Erling Smørgrav data[i] = 1527b5038d7SDag-Erling Smørgrav 16 * (uint8_t) ldns_hexdigit_to_int(str[i*2]) + 1537b5038d7SDag-Erling Smørgrav (uint8_t) ldns_hexdigit_to_int(str[i*2 + 1]); 1547b5038d7SDag-Erling Smørgrav } 1557b5038d7SDag-Erling Smørgrav 1567b5038d7SDag-Erling Smørgrav return (int) i; 1577b5038d7SDag-Erling Smørgrav } 1587b5038d7SDag-Erling Smørgrav 1597b5038d7SDag-Erling Smørgrav const char * 1607b5038d7SDag-Erling Smørgrav ldns_version(void) 1617b5038d7SDag-Erling Smørgrav { 1627b5038d7SDag-Erling Smørgrav return (char*)LDNS_VERSION; 1637b5038d7SDag-Erling Smørgrav } 1647b5038d7SDag-Erling Smørgrav 1657b5038d7SDag-Erling Smørgrav /* Number of days per month (except for February in leap years). */ 1667b5038d7SDag-Erling Smørgrav static const int mdays[] = { 1677b5038d7SDag-Erling Smørgrav 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 1687b5038d7SDag-Erling Smørgrav }; 1697b5038d7SDag-Erling Smørgrav 1707b5038d7SDag-Erling Smørgrav #define LDNS_MOD(x,y) (((x) % (y) < 0) ? ((x) % (y) + (y)) : ((x) % (y))) 1717b5038d7SDag-Erling Smørgrav #define LDNS_DIV(x,y) (((x) % (y) < 0) ? ((x) / (y) - 1 ) : ((x) / (y))) 1727b5038d7SDag-Erling Smørgrav 1737b5038d7SDag-Erling Smørgrav static int 1747b5038d7SDag-Erling Smørgrav is_leap_year(int year) 1757b5038d7SDag-Erling Smørgrav { 1767b5038d7SDag-Erling Smørgrav return LDNS_MOD(year, 4) == 0 && (LDNS_MOD(year, 100) != 0 1777b5038d7SDag-Erling Smørgrav || LDNS_MOD(year, 400) == 0); 1787b5038d7SDag-Erling Smørgrav } 1797b5038d7SDag-Erling Smørgrav 1807b5038d7SDag-Erling Smørgrav static int 1817b5038d7SDag-Erling Smørgrav leap_days(int y1, int y2) 1827b5038d7SDag-Erling Smørgrav { 1837b5038d7SDag-Erling Smørgrav --y1; 1847b5038d7SDag-Erling Smørgrav --y2; 1857b5038d7SDag-Erling Smørgrav return (LDNS_DIV(y2, 4) - LDNS_DIV(y1, 4)) - 1867b5038d7SDag-Erling Smørgrav (LDNS_DIV(y2, 100) - LDNS_DIV(y1, 100)) + 1877b5038d7SDag-Erling Smørgrav (LDNS_DIV(y2, 400) - LDNS_DIV(y1, 400)); 1887b5038d7SDag-Erling Smørgrav } 1897b5038d7SDag-Erling Smørgrav 1907b5038d7SDag-Erling Smørgrav /* 1917b5038d7SDag-Erling Smørgrav * Code adapted from Python 2.4.1 sources (Lib/calendar.py). 1927b5038d7SDag-Erling Smørgrav */ 1937b5038d7SDag-Erling Smørgrav time_t 1942787e39aSDag-Erling Smørgrav ldns_mktime_from_utc(const struct tm *tm) 1957b5038d7SDag-Erling Smørgrav { 1967b5038d7SDag-Erling Smørgrav int year = 1900 + tm->tm_year; 1977b5038d7SDag-Erling Smørgrav time_t days = 365 * ((time_t) year - 1970) + leap_days(1970, year); 1987b5038d7SDag-Erling Smørgrav time_t hours; 1997b5038d7SDag-Erling Smørgrav time_t minutes; 2007b5038d7SDag-Erling Smørgrav time_t seconds; 2017b5038d7SDag-Erling Smørgrav int i; 2027b5038d7SDag-Erling Smørgrav 2037b5038d7SDag-Erling Smørgrav for (i = 0; i < tm->tm_mon; ++i) { 2047b5038d7SDag-Erling Smørgrav days += mdays[i]; 2057b5038d7SDag-Erling Smørgrav } 2067b5038d7SDag-Erling Smørgrav if (tm->tm_mon > 1 && is_leap_year(year)) { 2077b5038d7SDag-Erling Smørgrav ++days; 2087b5038d7SDag-Erling Smørgrav } 2097b5038d7SDag-Erling Smørgrav days += tm->tm_mday - 1; 2107b5038d7SDag-Erling Smørgrav 2117b5038d7SDag-Erling Smørgrav hours = days * 24 + tm->tm_hour; 2127b5038d7SDag-Erling Smørgrav minutes = hours * 60 + tm->tm_min; 2137b5038d7SDag-Erling Smørgrav seconds = minutes * 60 + tm->tm_sec; 2147b5038d7SDag-Erling Smørgrav 2157b5038d7SDag-Erling Smørgrav return seconds; 2167b5038d7SDag-Erling Smørgrav } 2177b5038d7SDag-Erling Smørgrav 2182787e39aSDag-Erling Smørgrav time_t 2192787e39aSDag-Erling Smørgrav mktime_from_utc(const struct tm *tm) 2202787e39aSDag-Erling Smørgrav { 2212787e39aSDag-Erling Smørgrav return ldns_mktime_from_utc(tm); 2222787e39aSDag-Erling Smørgrav } 2232787e39aSDag-Erling Smørgrav 2247b5038d7SDag-Erling Smørgrav #if SIZEOF_TIME_T <= 4 2257b5038d7SDag-Erling Smørgrav 2267b5038d7SDag-Erling Smørgrav static void 2277b5038d7SDag-Erling Smørgrav ldns_year_and_yday_from_days_since_epoch(int64_t days, struct tm *result) 2287b5038d7SDag-Erling Smørgrav { 2297b5038d7SDag-Erling Smørgrav int year = 1970; 2307b5038d7SDag-Erling Smørgrav int new_year; 2317b5038d7SDag-Erling Smørgrav 2327b5038d7SDag-Erling Smørgrav while (days < 0 || days >= (int64_t) (is_leap_year(year) ? 366 : 365)) { 2337b5038d7SDag-Erling Smørgrav new_year = year + (int) LDNS_DIV(days, 365); 2347b5038d7SDag-Erling Smørgrav days -= (new_year - year) * 365; 2357b5038d7SDag-Erling Smørgrav days -= leap_days(year, new_year); 2367b5038d7SDag-Erling Smørgrav year = new_year; 2377b5038d7SDag-Erling Smørgrav } 2387b5038d7SDag-Erling Smørgrav result->tm_year = year; 2397b5038d7SDag-Erling Smørgrav result->tm_yday = (int) days; 2407b5038d7SDag-Erling Smørgrav } 2417b5038d7SDag-Erling Smørgrav 2427b5038d7SDag-Erling Smørgrav /* Number of days per month in a leap year. */ 2437b5038d7SDag-Erling Smørgrav static const int leap_year_mdays[] = { 2447b5038d7SDag-Erling Smørgrav 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 2457b5038d7SDag-Erling Smørgrav }; 2467b5038d7SDag-Erling Smørgrav 2477b5038d7SDag-Erling Smørgrav static void 2487b5038d7SDag-Erling Smørgrav ldns_mon_and_mday_from_year_and_yday(struct tm *result) 2497b5038d7SDag-Erling Smørgrav { 2507b5038d7SDag-Erling Smørgrav int idays = result->tm_yday; 2517b5038d7SDag-Erling Smørgrav const int *mon_lengths = is_leap_year(result->tm_year) ? 2527b5038d7SDag-Erling Smørgrav leap_year_mdays : mdays; 2537b5038d7SDag-Erling Smørgrav 2547b5038d7SDag-Erling Smørgrav result->tm_mon = 0; 2557b5038d7SDag-Erling Smørgrav while (idays >= mon_lengths[result->tm_mon]) { 2567b5038d7SDag-Erling Smørgrav idays -= mon_lengths[result->tm_mon++]; 2577b5038d7SDag-Erling Smørgrav } 2587b5038d7SDag-Erling Smørgrav result->tm_mday = idays + 1; 2597b5038d7SDag-Erling Smørgrav } 2607b5038d7SDag-Erling Smørgrav 2617b5038d7SDag-Erling Smørgrav static void 2627b5038d7SDag-Erling Smørgrav ldns_wday_from_year_and_yday(struct tm *result) 2637b5038d7SDag-Erling Smørgrav { 2647b5038d7SDag-Erling Smørgrav result->tm_wday = 4 /* 1-1-1970 was a thursday */ 2657b5038d7SDag-Erling Smørgrav + LDNS_MOD((result->tm_year - 1970), 7) * LDNS_MOD(365, 7) 2667b5038d7SDag-Erling Smørgrav + leap_days(1970, result->tm_year) 2677b5038d7SDag-Erling Smørgrav + result->tm_yday; 2687b5038d7SDag-Erling Smørgrav result->tm_wday = LDNS_MOD(result->tm_wday, 7); 2697b5038d7SDag-Erling Smørgrav if (result->tm_wday < 0) { 2707b5038d7SDag-Erling Smørgrav result->tm_wday += 7; 2717b5038d7SDag-Erling Smørgrav } 2727b5038d7SDag-Erling Smørgrav } 2737b5038d7SDag-Erling Smørgrav 2747b5038d7SDag-Erling Smørgrav static struct tm * 2757b5038d7SDag-Erling Smørgrav ldns_gmtime64_r(int64_t clock, struct tm *result) 2767b5038d7SDag-Erling Smørgrav { 2777b5038d7SDag-Erling Smørgrav result->tm_isdst = 0; 2787b5038d7SDag-Erling Smørgrav result->tm_sec = (int) LDNS_MOD(clock, 60); 2797b5038d7SDag-Erling Smørgrav clock = LDNS_DIV(clock, 60); 2807b5038d7SDag-Erling Smørgrav result->tm_min = (int) LDNS_MOD(clock, 60); 2817b5038d7SDag-Erling Smørgrav clock = LDNS_DIV(clock, 60); 2827b5038d7SDag-Erling Smørgrav result->tm_hour = (int) LDNS_MOD(clock, 24); 2837b5038d7SDag-Erling Smørgrav clock = LDNS_DIV(clock, 24); 2847b5038d7SDag-Erling Smørgrav 2857b5038d7SDag-Erling Smørgrav ldns_year_and_yday_from_days_since_epoch(clock, result); 2867b5038d7SDag-Erling Smørgrav ldns_mon_and_mday_from_year_and_yday(result); 2877b5038d7SDag-Erling Smørgrav ldns_wday_from_year_and_yday(result); 2887b5038d7SDag-Erling Smørgrav result->tm_year -= 1900; 2897b5038d7SDag-Erling Smørgrav 2907b5038d7SDag-Erling Smørgrav return result; 2917b5038d7SDag-Erling Smørgrav } 2927b5038d7SDag-Erling Smørgrav 2937b5038d7SDag-Erling Smørgrav #endif /* SIZEOF_TIME_T <= 4 */ 2947b5038d7SDag-Erling Smørgrav 2957b5038d7SDag-Erling Smørgrav static int64_t 2967b5038d7SDag-Erling Smørgrav ldns_serial_arithmitics_time(int32_t time, time_t now) 2977b5038d7SDag-Erling Smørgrav { 2987b5038d7SDag-Erling Smørgrav int32_t offset = time - (int32_t) now; 2997b5038d7SDag-Erling Smørgrav return (int64_t) now + offset; 3007b5038d7SDag-Erling Smørgrav } 3017b5038d7SDag-Erling Smørgrav 3027b5038d7SDag-Erling Smørgrav 3037b5038d7SDag-Erling Smørgrav struct tm * 3047b5038d7SDag-Erling Smørgrav ldns_serial_arithmitics_gmtime_r(int32_t time, time_t now, struct tm *result) 3057b5038d7SDag-Erling Smørgrav { 3067b5038d7SDag-Erling Smørgrav #if SIZEOF_TIME_T <= 4 3077b5038d7SDag-Erling Smørgrav int64_t secs_since_epoch = ldns_serial_arithmitics_time(time, now); 3087b5038d7SDag-Erling Smørgrav return ldns_gmtime64_r(secs_since_epoch, result); 3097b5038d7SDag-Erling Smørgrav #else 3107b5038d7SDag-Erling Smørgrav time_t secs_since_epoch = ldns_serial_arithmitics_time(time, now); 3117b5038d7SDag-Erling Smørgrav return gmtime_r(&secs_since_epoch, result); 3127b5038d7SDag-Erling Smørgrav #endif 3137b5038d7SDag-Erling Smørgrav } 3147b5038d7SDag-Erling Smørgrav 3157b5038d7SDag-Erling Smørgrav /** 3167b5038d7SDag-Erling Smørgrav * Init the random source 3177b5038d7SDag-Erling Smørgrav * applications should call this if they need entropy data within ldns 3187b5038d7SDag-Erling Smørgrav * If openSSL is available, it is automatically seeded from /dev/urandom 3197b5038d7SDag-Erling Smørgrav * or /dev/random 3207b5038d7SDag-Erling Smørgrav * 3217b5038d7SDag-Erling Smørgrav * If you need more entropy, or have no openssl available, this function 3227b5038d7SDag-Erling Smørgrav * MUST be called at the start of the program 3237b5038d7SDag-Erling Smørgrav * 3247b5038d7SDag-Erling Smørgrav * If openssl *is* available, this function just adds more entropy 3257b5038d7SDag-Erling Smørgrav **/ 3267b5038d7SDag-Erling Smørgrav int 3277b5038d7SDag-Erling Smørgrav ldns_init_random(FILE *fd, unsigned int size) 3287b5038d7SDag-Erling Smørgrav { 3297b5038d7SDag-Erling Smørgrav /* if fp is given, seed srandom with data from file 3307b5038d7SDag-Erling Smørgrav otherwise use /dev/urandom */ 3317b5038d7SDag-Erling Smørgrav FILE *rand_f; 3327b5038d7SDag-Erling Smørgrav uint8_t *seed; 3337b5038d7SDag-Erling Smørgrav size_t read = 0; 3347b5038d7SDag-Erling Smørgrav unsigned int seed_i; 3357b5038d7SDag-Erling Smørgrav struct timeval tv; 3367b5038d7SDag-Erling Smørgrav 3377b5038d7SDag-Erling Smørgrav /* we'll need at least sizeof(unsigned int) bytes for the 3387b5038d7SDag-Erling Smørgrav standard prng seed */ 3397b5038d7SDag-Erling Smørgrav if (size < (unsigned int) sizeof(seed_i)){ 3407b5038d7SDag-Erling Smørgrav size = (unsigned int) sizeof(seed_i); 3417b5038d7SDag-Erling Smørgrav } 3427b5038d7SDag-Erling Smørgrav 3437b5038d7SDag-Erling Smørgrav seed = LDNS_XMALLOC(uint8_t, size); 3447b5038d7SDag-Erling Smørgrav if(!seed) { 3457b5038d7SDag-Erling Smørgrav return 1; 3467b5038d7SDag-Erling Smørgrav } 3477b5038d7SDag-Erling Smørgrav 3487b5038d7SDag-Erling Smørgrav if (!fd) { 3497b5038d7SDag-Erling Smørgrav if ((rand_f = fopen("/dev/urandom", "r")) == NULL) { 3507b5038d7SDag-Erling Smørgrav /* no readable /dev/urandom, try /dev/random */ 3517b5038d7SDag-Erling Smørgrav if ((rand_f = fopen("/dev/random", "r")) == NULL) { 3527b5038d7SDag-Erling Smørgrav /* no readable /dev/random either, and no entropy 3537b5038d7SDag-Erling Smørgrav source given. we'll have to improvise */ 3547b5038d7SDag-Erling Smørgrav for (read = 0; read < size; read++) { 3557b5038d7SDag-Erling Smørgrav gettimeofday(&tv, NULL); 3567b5038d7SDag-Erling Smørgrav seed[read] = (uint8_t) (tv.tv_usec % 256); 3577b5038d7SDag-Erling Smørgrav } 3587b5038d7SDag-Erling Smørgrav } else { 3597b5038d7SDag-Erling Smørgrav read = fread(seed, 1, size, rand_f); 3607b5038d7SDag-Erling Smørgrav } 3617b5038d7SDag-Erling Smørgrav } else { 3627b5038d7SDag-Erling Smørgrav read = fread(seed, 1, size, rand_f); 3637b5038d7SDag-Erling Smørgrav } 3647b5038d7SDag-Erling Smørgrav } else { 3657b5038d7SDag-Erling Smørgrav rand_f = fd; 3667b5038d7SDag-Erling Smørgrav read = fread(seed, 1, size, rand_f); 3677b5038d7SDag-Erling Smørgrav } 3687b5038d7SDag-Erling Smørgrav 3697b5038d7SDag-Erling Smørgrav if (read < size) { 3707b5038d7SDag-Erling Smørgrav LDNS_FREE(seed); 3712787e39aSDag-Erling Smørgrav if (!fd) fclose(rand_f); 3727b5038d7SDag-Erling Smørgrav return 1; 3737b5038d7SDag-Erling Smørgrav } else { 3747b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL 3757b5038d7SDag-Erling Smørgrav /* Seed the OpenSSL prng (most systems have it seeded 3767b5038d7SDag-Erling Smørgrav automatically, in that case this call just adds entropy */ 3777b5038d7SDag-Erling Smørgrav RAND_seed(seed, (int) size); 3787b5038d7SDag-Erling Smørgrav #else 3797b5038d7SDag-Erling Smørgrav /* Seed the standard prng, only uses the first 3807b5038d7SDag-Erling Smørgrav * unsigned sizeof(unsiged int) bytes found in the entropy pool 3817b5038d7SDag-Erling Smørgrav */ 3827b5038d7SDag-Erling Smørgrav memcpy(&seed_i, seed, sizeof(seed_i)); 3837b5038d7SDag-Erling Smørgrav srandom(seed_i); 3847b5038d7SDag-Erling Smørgrav #endif 3857b5038d7SDag-Erling Smørgrav LDNS_FREE(seed); 3867b5038d7SDag-Erling Smørgrav } 3877b5038d7SDag-Erling Smørgrav 3887b5038d7SDag-Erling Smørgrav if (!fd) { 3897b5038d7SDag-Erling Smørgrav if (rand_f) fclose(rand_f); 3907b5038d7SDag-Erling Smørgrav } 3917b5038d7SDag-Erling Smørgrav 3927b5038d7SDag-Erling Smørgrav return 0; 3937b5038d7SDag-Erling Smørgrav } 3947b5038d7SDag-Erling Smørgrav 3957b5038d7SDag-Erling Smørgrav /** 3967b5038d7SDag-Erling Smørgrav * Get random number. 3977b5038d7SDag-Erling Smørgrav * 3987b5038d7SDag-Erling Smørgrav */ 3997b5038d7SDag-Erling Smørgrav uint16_t 4007b5038d7SDag-Erling Smørgrav ldns_get_random(void) 4017b5038d7SDag-Erling Smørgrav { 4027b5038d7SDag-Erling Smørgrav uint16_t rid = 0; 4037b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL 4047b5038d7SDag-Erling Smørgrav if (RAND_bytes((unsigned char*)&rid, 2) != 1) { 4057b5038d7SDag-Erling Smørgrav rid = (uint16_t) random(); 4067b5038d7SDag-Erling Smørgrav } 4077b5038d7SDag-Erling Smørgrav #else 4087b5038d7SDag-Erling Smørgrav rid = (uint16_t) random(); 4097b5038d7SDag-Erling Smørgrav #endif 4107b5038d7SDag-Erling Smørgrav return rid; 4117b5038d7SDag-Erling Smørgrav } 4127b5038d7SDag-Erling Smørgrav 4137b5038d7SDag-Erling Smørgrav /* 4147b5038d7SDag-Erling Smørgrav * BubbleBabble code taken from OpenSSH 4157b5038d7SDag-Erling Smørgrav * Copyright (c) 2001 Carsten Raskgaard. All rights reserved. 4167b5038d7SDag-Erling Smørgrav */ 4177b5038d7SDag-Erling Smørgrav char * 4187b5038d7SDag-Erling Smørgrav ldns_bubblebabble(uint8_t *data, size_t len) 4197b5038d7SDag-Erling Smørgrav { 4207b5038d7SDag-Erling Smørgrav char vowels[] = { 'a', 'e', 'i', 'o', 'u', 'y' }; 4217b5038d7SDag-Erling Smørgrav char consonants[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm', 4227b5038d7SDag-Erling Smørgrav 'n', 'p', 'r', 's', 't', 'v', 'z', 'x' }; 4237b5038d7SDag-Erling Smørgrav size_t i, j = 0, rounds, seed = 1; 4247b5038d7SDag-Erling Smørgrav char *retval; 4257b5038d7SDag-Erling Smørgrav 4267b5038d7SDag-Erling Smørgrav rounds = (len / 2) + 1; 4277b5038d7SDag-Erling Smørgrav retval = LDNS_XMALLOC(char, rounds * 6); 4287b5038d7SDag-Erling Smørgrav if(!retval) return NULL; 4297b5038d7SDag-Erling Smørgrav retval[j++] = 'x'; 4307b5038d7SDag-Erling Smørgrav for (i = 0; i < rounds; i++) { 4317b5038d7SDag-Erling Smørgrav size_t idx0, idx1, idx2, idx3, idx4; 4327b5038d7SDag-Erling Smørgrav if ((i + 1 < rounds) || (len % 2 != 0)) { 4337b5038d7SDag-Erling Smørgrav idx0 = (((((size_t)(data[2 * i])) >> 6) & 3) + 4347b5038d7SDag-Erling Smørgrav seed) % 6; 4357b5038d7SDag-Erling Smørgrav idx1 = (((size_t)(data[2 * i])) >> 2) & 15; 4367b5038d7SDag-Erling Smørgrav idx2 = ((((size_t)(data[2 * i])) & 3) + 4377b5038d7SDag-Erling Smørgrav (seed / 6)) % 6; 4387b5038d7SDag-Erling Smørgrav retval[j++] = vowels[idx0]; 4397b5038d7SDag-Erling Smørgrav retval[j++] = consonants[idx1]; 4407b5038d7SDag-Erling Smørgrav retval[j++] = vowels[idx2]; 4417b5038d7SDag-Erling Smørgrav if ((i + 1) < rounds) { 4427b5038d7SDag-Erling Smørgrav idx3 = (((size_t)(data[(2 * i) + 1])) >> 4) & 15; 4437b5038d7SDag-Erling Smørgrav idx4 = (((size_t)(data[(2 * i) + 1]))) & 15; 4447b5038d7SDag-Erling Smørgrav retval[j++] = consonants[idx3]; 4457b5038d7SDag-Erling Smørgrav retval[j++] = '-'; 4467b5038d7SDag-Erling Smørgrav retval[j++] = consonants[idx4]; 4477b5038d7SDag-Erling Smørgrav seed = ((seed * 5) + 4487b5038d7SDag-Erling Smørgrav ((((size_t)(data[2 * i])) * 7) + 4497b5038d7SDag-Erling Smørgrav ((size_t)(data[(2 * i) + 1])))) % 36; 4507b5038d7SDag-Erling Smørgrav } 4517b5038d7SDag-Erling Smørgrav } else { 4527b5038d7SDag-Erling Smørgrav idx0 = seed % 6; 4537b5038d7SDag-Erling Smørgrav idx1 = 16; 4547b5038d7SDag-Erling Smørgrav idx2 = seed / 6; 4557b5038d7SDag-Erling Smørgrav retval[j++] = vowels[idx0]; 4567b5038d7SDag-Erling Smørgrav retval[j++] = consonants[idx1]; 4577b5038d7SDag-Erling Smørgrav retval[j++] = vowels[idx2]; 4587b5038d7SDag-Erling Smørgrav } 4597b5038d7SDag-Erling Smørgrav } 4607b5038d7SDag-Erling Smørgrav retval[j++] = 'x'; 4617b5038d7SDag-Erling Smørgrav retval[j++] = '\0'; 4627b5038d7SDag-Erling Smørgrav return retval; 4637b5038d7SDag-Erling Smørgrav } 464*17d15b25SDag-Erling Smørgrav 465*17d15b25SDag-Erling Smørgrav /* 466*17d15b25SDag-Erling Smørgrav * For backwards compatibility, because we have always exported this symbol. 467*17d15b25SDag-Erling Smørgrav */ 468*17d15b25SDag-Erling Smørgrav #ifdef HAVE_B64_NTOP 469*17d15b25SDag-Erling Smørgrav int ldns_b64_ntop(const uint8_t* src, size_t srclength, 470*17d15b25SDag-Erling Smørgrav char *target, size_t targsize); 471*17d15b25SDag-Erling Smørgrav { 472*17d15b25SDag-Erling Smørgrav return b64_ntop(src, srclength, target, targsize); 473*17d15b25SDag-Erling Smørgrav } 474*17d15b25SDag-Erling Smørgrav #endif 475*17d15b25SDag-Erling Smørgrav 476*17d15b25SDag-Erling Smørgrav /* 477*17d15b25SDag-Erling Smørgrav * For backwards compatibility, because we have always exported this symbol. 478*17d15b25SDag-Erling Smørgrav */ 479*17d15b25SDag-Erling Smørgrav #ifdef HAVE_B64_PTON 480*17d15b25SDag-Erling Smørgrav int ldns_b64_pton(const char* src, uint8_t *target, size_t targsize) 481*17d15b25SDag-Erling Smørgrav { 482*17d15b25SDag-Erling Smørgrav return b64_pton(src, target, targsize); 483*17d15b25SDag-Erling Smørgrav } 484*17d15b25SDag-Erling Smørgrav #endif 485*17d15b25SDag-Erling Smørgrav 486*17d15b25SDag-Erling Smørgrav 487*17d15b25SDag-Erling Smørgrav static int 488*17d15b25SDag-Erling Smørgrav ldns_b32_ntop_base(const uint8_t* src, size_t src_sz, 489*17d15b25SDag-Erling Smørgrav char* dst, size_t dst_sz, 490*17d15b25SDag-Erling Smørgrav bool extended_hex, bool add_padding) 491*17d15b25SDag-Erling Smørgrav { 492*17d15b25SDag-Erling Smørgrav size_t ret_sz; 493*17d15b25SDag-Erling Smørgrav const char* b32 = extended_hex ? "0123456789abcdefghijklmnopqrstuv" 494*17d15b25SDag-Erling Smørgrav : "abcdefghijklmnopqrstuvwxyz234567"; 495*17d15b25SDag-Erling Smørgrav 496*17d15b25SDag-Erling Smørgrav size_t c = 0; /* c is used to carry partial base32 character over 497*17d15b25SDag-Erling Smørgrav * byte boundaries for sizes with a remainder. 498*17d15b25SDag-Erling Smørgrav * (i.e. src_sz % 5 != 0) 499*17d15b25SDag-Erling Smørgrav */ 500*17d15b25SDag-Erling Smørgrav 501*17d15b25SDag-Erling Smørgrav ret_sz = add_padding ? ldns_b32_ntop_calculate_size(src_sz) 502*17d15b25SDag-Erling Smørgrav : ldns_b32_ntop_calculate_size_no_padding(src_sz); 503*17d15b25SDag-Erling Smørgrav 504*17d15b25SDag-Erling Smørgrav /* Do we have enough space? */ 505*17d15b25SDag-Erling Smørgrav if (dst_sz < ret_sz + 1) 506*17d15b25SDag-Erling Smørgrav return -1; 507*17d15b25SDag-Erling Smørgrav 508*17d15b25SDag-Erling Smørgrav /* We know the size; terminate the string */ 509*17d15b25SDag-Erling Smørgrav dst[ret_sz] = '\0'; 510*17d15b25SDag-Erling Smørgrav 511*17d15b25SDag-Erling Smørgrav /* First process all chunks of five */ 512*17d15b25SDag-Erling Smørgrav while (src_sz >= 5) { 513*17d15b25SDag-Erling Smørgrav /* 00000... ........ ........ ........ ........ */ 514*17d15b25SDag-Erling Smørgrav dst[0] = b32[(src[0] ) >> 3]; 515*17d15b25SDag-Erling Smørgrav 516*17d15b25SDag-Erling Smørgrav /* .....111 11...... ........ ........ ........ */ 517*17d15b25SDag-Erling Smørgrav dst[1] = b32[(src[0] & 0x07) << 2 | src[1] >> 6]; 518*17d15b25SDag-Erling Smørgrav 519*17d15b25SDag-Erling Smørgrav /* ........ ..22222. ........ ........ ........ */ 520*17d15b25SDag-Erling Smørgrav dst[2] = b32[(src[1] & 0x3e) >> 1]; 521*17d15b25SDag-Erling Smørgrav 522*17d15b25SDag-Erling Smørgrav /* ........ .......3 3333.... ........ ........ */ 523*17d15b25SDag-Erling Smørgrav dst[3] = b32[(src[1] & 0x01) << 4 | src[2] >> 4]; 524*17d15b25SDag-Erling Smørgrav 525*17d15b25SDag-Erling Smørgrav /* ........ ........ ....4444 4....... ........ */ 526*17d15b25SDag-Erling Smørgrav dst[4] = b32[(src[2] & 0x0f) << 1 | src[3] >> 7]; 527*17d15b25SDag-Erling Smørgrav 528*17d15b25SDag-Erling Smørgrav /* ........ ........ ........ .55555.. ........ */ 529*17d15b25SDag-Erling Smørgrav dst[5] = b32[(src[3] & 0x7c) >> 2]; 530*17d15b25SDag-Erling Smørgrav 531*17d15b25SDag-Erling Smørgrav /* ........ ........ ........ ......66 666..... */ 532*17d15b25SDag-Erling Smørgrav dst[6] = b32[(src[3] & 0x03) << 3 | src[4] >> 5]; 533*17d15b25SDag-Erling Smørgrav 534*17d15b25SDag-Erling Smørgrav /* ........ ........ ........ ........ ...77777 */ 535*17d15b25SDag-Erling Smørgrav dst[7] = b32[(src[4] & 0x1f) ]; 536*17d15b25SDag-Erling Smørgrav 537*17d15b25SDag-Erling Smørgrav src_sz -= 5; 538*17d15b25SDag-Erling Smørgrav src += 5; 539*17d15b25SDag-Erling Smørgrav dst += 8; 540*17d15b25SDag-Erling Smørgrav } 541*17d15b25SDag-Erling Smørgrav /* Process what remains */ 542*17d15b25SDag-Erling Smørgrav switch (src_sz) { 543*17d15b25SDag-Erling Smørgrav case 4: /* ........ ........ ........ ......66 666..... */ 544*17d15b25SDag-Erling Smørgrav dst[6] = b32[(src[3] & 0x03) << 3]; 545*17d15b25SDag-Erling Smørgrav 546*17d15b25SDag-Erling Smørgrav /* ........ ........ ........ .55555.. ........ */ 547*17d15b25SDag-Erling Smørgrav dst[5] = b32[(src[3] & 0x7c) >> 2]; 548*17d15b25SDag-Erling Smørgrav 549*17d15b25SDag-Erling Smørgrav /* ........ ........ ....4444 4....... ........ */ 550*17d15b25SDag-Erling Smørgrav c = src[3] >> 7 ; 551*17d15b25SDag-Erling Smørgrav case 3: dst[4] = b32[(src[2] & 0x0f) << 1 | c]; 552*17d15b25SDag-Erling Smørgrav 553*17d15b25SDag-Erling Smørgrav /* ........ .......3 3333.... ........ ........ */ 554*17d15b25SDag-Erling Smørgrav c = src[2] >> 4 ; 555*17d15b25SDag-Erling Smørgrav case 2: dst[3] = b32[(src[1] & 0x01) << 4 | c]; 556*17d15b25SDag-Erling Smørgrav 557*17d15b25SDag-Erling Smørgrav /* ........ ..22222. ........ ........ ........ */ 558*17d15b25SDag-Erling Smørgrav dst[2] = b32[(src[1] & 0x3e) >> 1]; 559*17d15b25SDag-Erling Smørgrav 560*17d15b25SDag-Erling Smørgrav /* .....111 11...... ........ ........ ........ */ 561*17d15b25SDag-Erling Smørgrav c = src[1] >> 6 ; 562*17d15b25SDag-Erling Smørgrav case 1: dst[1] = b32[(src[0] & 0x07) << 2 | c]; 563*17d15b25SDag-Erling Smørgrav 564*17d15b25SDag-Erling Smørgrav /* 00000... ........ ........ ........ ........ */ 565*17d15b25SDag-Erling Smørgrav dst[0] = b32[ src[0] >> 3]; 566*17d15b25SDag-Erling Smørgrav } 567*17d15b25SDag-Erling Smørgrav /* Add padding */ 568*17d15b25SDag-Erling Smørgrav if (add_padding) { 569*17d15b25SDag-Erling Smørgrav switch (src_sz) { 570*17d15b25SDag-Erling Smørgrav case 1: dst[2] = '='; 571*17d15b25SDag-Erling Smørgrav dst[3] = '='; 572*17d15b25SDag-Erling Smørgrav case 2: dst[4] = '='; 573*17d15b25SDag-Erling Smørgrav case 3: dst[5] = '='; 574*17d15b25SDag-Erling Smørgrav dst[6] = '='; 575*17d15b25SDag-Erling Smørgrav case 4: dst[7] = '='; 576*17d15b25SDag-Erling Smørgrav } 577*17d15b25SDag-Erling Smørgrav } 578*17d15b25SDag-Erling Smørgrav return (int)ret_sz; 579*17d15b25SDag-Erling Smørgrav } 580*17d15b25SDag-Erling Smørgrav 581*17d15b25SDag-Erling Smørgrav int 582*17d15b25SDag-Erling Smørgrav ldns_b32_ntop(const uint8_t* src, size_t src_sz, char* dst, size_t dst_sz) 583*17d15b25SDag-Erling Smørgrav { 584*17d15b25SDag-Erling Smørgrav return ldns_b32_ntop_base(src, src_sz, dst, dst_sz, false, true); 585*17d15b25SDag-Erling Smørgrav } 586*17d15b25SDag-Erling Smørgrav 587*17d15b25SDag-Erling Smørgrav int 588*17d15b25SDag-Erling Smørgrav ldns_b32_ntop_extended_hex(const uint8_t* src, size_t src_sz, 589*17d15b25SDag-Erling Smørgrav char* dst, size_t dst_sz) 590*17d15b25SDag-Erling Smørgrav { 591*17d15b25SDag-Erling Smørgrav return ldns_b32_ntop_base(src, src_sz, dst, dst_sz, true, true); 592*17d15b25SDag-Erling Smørgrav } 593*17d15b25SDag-Erling Smørgrav 594*17d15b25SDag-Erling Smørgrav #ifndef HAVE_B32_NTOP 595*17d15b25SDag-Erling Smørgrav 596*17d15b25SDag-Erling Smørgrav int 597*17d15b25SDag-Erling Smørgrav b32_ntop(const uint8_t* src, size_t src_sz, char* dst, size_t dst_sz) 598*17d15b25SDag-Erling Smørgrav { 599*17d15b25SDag-Erling Smørgrav return ldns_b32_ntop_base(src, src_sz, dst, dst_sz, false, true); 600*17d15b25SDag-Erling Smørgrav } 601*17d15b25SDag-Erling Smørgrav 602*17d15b25SDag-Erling Smørgrav int 603*17d15b25SDag-Erling Smørgrav b32_ntop_extended_hex(const uint8_t* src, size_t src_sz, 604*17d15b25SDag-Erling Smørgrav char* dst, size_t dst_sz) 605*17d15b25SDag-Erling Smørgrav { 606*17d15b25SDag-Erling Smørgrav return ldns_b32_ntop_base(src, src_sz, dst, dst_sz, true, true); 607*17d15b25SDag-Erling Smørgrav } 608*17d15b25SDag-Erling Smørgrav 609*17d15b25SDag-Erling Smørgrav #endif /* ! HAVE_B32_NTOP */ 610*17d15b25SDag-Erling Smørgrav 611*17d15b25SDag-Erling Smørgrav static int 612*17d15b25SDag-Erling Smørgrav ldns_b32_pton_base(const char* src, size_t src_sz, 613*17d15b25SDag-Erling Smørgrav uint8_t* dst, size_t dst_sz, 614*17d15b25SDag-Erling Smørgrav bool extended_hex, bool check_padding) 615*17d15b25SDag-Erling Smørgrav { 616*17d15b25SDag-Erling Smørgrav size_t i = 0; 617*17d15b25SDag-Erling Smørgrav char ch = '\0'; 618*17d15b25SDag-Erling Smørgrav uint8_t buf[8]; 619*17d15b25SDag-Erling Smørgrav uint8_t* start = dst; 620*17d15b25SDag-Erling Smørgrav 621*17d15b25SDag-Erling Smørgrav while (src_sz) { 622*17d15b25SDag-Erling Smørgrav /* Collect 8 characters in buf (if possible) */ 623*17d15b25SDag-Erling Smørgrav for (i = 0; i < 8; i++) { 624*17d15b25SDag-Erling Smørgrav 625*17d15b25SDag-Erling Smørgrav do { 626*17d15b25SDag-Erling Smørgrav ch = *src++; 627*17d15b25SDag-Erling Smørgrav --src_sz; 628*17d15b25SDag-Erling Smørgrav 629*17d15b25SDag-Erling Smørgrav } while (isspace(ch) && src_sz > 0); 630*17d15b25SDag-Erling Smørgrav 631*17d15b25SDag-Erling Smørgrav if (ch == '=' || ch == '\0') 632*17d15b25SDag-Erling Smørgrav break; 633*17d15b25SDag-Erling Smørgrav 634*17d15b25SDag-Erling Smørgrav else if (extended_hex) 635*17d15b25SDag-Erling Smørgrav 636*17d15b25SDag-Erling Smørgrav if (ch >= '0' && ch <= '9') 637*17d15b25SDag-Erling Smørgrav buf[i] = (uint8_t)ch - '0'; 638*17d15b25SDag-Erling Smørgrav else if (ch >= 'a' && ch <= 'v') 639*17d15b25SDag-Erling Smørgrav buf[i] = (uint8_t)ch - 'a' + 10; 640*17d15b25SDag-Erling Smørgrav else if (ch >= 'A' && ch <= 'V') 641*17d15b25SDag-Erling Smørgrav buf[i] = (uint8_t)ch - 'A' + 10; 642*17d15b25SDag-Erling Smørgrav else 643*17d15b25SDag-Erling Smørgrav return -1; 644*17d15b25SDag-Erling Smørgrav 645*17d15b25SDag-Erling Smørgrav else if (ch >= 'a' && ch <= 'z') 646*17d15b25SDag-Erling Smørgrav buf[i] = (uint8_t)ch - 'a'; 647*17d15b25SDag-Erling Smørgrav else if (ch >= 'A' && ch <= 'Z') 648*17d15b25SDag-Erling Smørgrav buf[i] = (uint8_t)ch - 'A'; 649*17d15b25SDag-Erling Smørgrav else if (ch >= '2' && ch <= '7') 650*17d15b25SDag-Erling Smørgrav buf[i] = (uint8_t)ch - '2' + 26; 651*17d15b25SDag-Erling Smørgrav else 652*17d15b25SDag-Erling Smørgrav return -1; 653*17d15b25SDag-Erling Smørgrav } 654*17d15b25SDag-Erling Smørgrav /* Less that 8 characters. We're done. */ 655*17d15b25SDag-Erling Smørgrav if (i < 8) 656*17d15b25SDag-Erling Smørgrav break; 657*17d15b25SDag-Erling Smørgrav 658*17d15b25SDag-Erling Smørgrav /* Enough space available at the destination? */ 659*17d15b25SDag-Erling Smørgrav if (dst_sz < 5) 660*17d15b25SDag-Erling Smørgrav return -1; 661*17d15b25SDag-Erling Smørgrav 662*17d15b25SDag-Erling Smørgrav /* 00000... ........ ........ ........ ........ */ 663*17d15b25SDag-Erling Smørgrav /* .....111 11...... ........ ........ ........ */ 664*17d15b25SDag-Erling Smørgrav dst[0] = buf[0] << 3 | buf[1] >> 2; 665*17d15b25SDag-Erling Smørgrav 666*17d15b25SDag-Erling Smørgrav /* .....111 11...... ........ ........ ........ */ 667*17d15b25SDag-Erling Smørgrav /* ........ ..22222. ........ ........ ........ */ 668*17d15b25SDag-Erling Smørgrav /* ........ .......3 3333.... ........ ........ */ 669*17d15b25SDag-Erling Smørgrav dst[1] = buf[1] << 6 | buf[2] << 1 | buf[3] >> 4; 670*17d15b25SDag-Erling Smørgrav 671*17d15b25SDag-Erling Smørgrav /* ........ .......3 3333.... ........ ........ */ 672*17d15b25SDag-Erling Smørgrav /* ........ ........ ....4444 4....... ........ */ 673*17d15b25SDag-Erling Smørgrav dst[2] = buf[3] << 4 | buf[4] >> 1; 674*17d15b25SDag-Erling Smørgrav 675*17d15b25SDag-Erling Smørgrav /* ........ ........ ....4444 4....... ........ */ 676*17d15b25SDag-Erling Smørgrav /* ........ ........ ........ .55555.. ........ */ 677*17d15b25SDag-Erling Smørgrav /* ........ ........ ........ ......66 666..... */ 678*17d15b25SDag-Erling Smørgrav dst[3] = buf[4] << 7 | buf[5] << 2 | buf[6] >> 3; 679*17d15b25SDag-Erling Smørgrav 680*17d15b25SDag-Erling Smørgrav /* ........ ........ ........ ......66 666..... */ 681*17d15b25SDag-Erling Smørgrav /* ........ ........ ........ ........ ...77777 */ 682*17d15b25SDag-Erling Smørgrav dst[4] = buf[6] << 5 | buf[7]; 683*17d15b25SDag-Erling Smørgrav 684*17d15b25SDag-Erling Smørgrav dst += 5; 685*17d15b25SDag-Erling Smørgrav dst_sz -= 5; 686*17d15b25SDag-Erling Smørgrav } 687*17d15b25SDag-Erling Smørgrav /* Not ending on a eight byte boundary? */ 688*17d15b25SDag-Erling Smørgrav if (i > 0 && i < 8) { 689*17d15b25SDag-Erling Smørgrav 690*17d15b25SDag-Erling Smørgrav /* Enough space available at the destination? */ 691*17d15b25SDag-Erling Smørgrav if (dst_sz < (i + 1) / 2) 692*17d15b25SDag-Erling Smørgrav return -1; 693*17d15b25SDag-Erling Smørgrav 694*17d15b25SDag-Erling Smørgrav switch (i) { 695*17d15b25SDag-Erling Smørgrav case 7: /* ........ ........ ........ ......66 666..... */ 696*17d15b25SDag-Erling Smørgrav /* ........ ........ ........ .55555.. ........ */ 697*17d15b25SDag-Erling Smørgrav /* ........ ........ ....4444 4....... ........ */ 698*17d15b25SDag-Erling Smørgrav dst[3] = buf[4] << 7 | buf[5] << 2 | buf[6] >> 3; 699*17d15b25SDag-Erling Smørgrav 700*17d15b25SDag-Erling Smørgrav case 5: /* ........ ........ ....4444 4....... ........ */ 701*17d15b25SDag-Erling Smørgrav /* ........ .......3 3333.... ........ ........ */ 702*17d15b25SDag-Erling Smørgrav dst[2] = buf[3] << 4 | buf[4] >> 1; 703*17d15b25SDag-Erling Smørgrav 704*17d15b25SDag-Erling Smørgrav case 4: /* ........ .......3 3333.... ........ ........ */ 705*17d15b25SDag-Erling Smørgrav /* ........ ..22222. ........ ........ ........ */ 706*17d15b25SDag-Erling Smørgrav /* .....111 11...... ........ ........ ........ */ 707*17d15b25SDag-Erling Smørgrav dst[1] = buf[1] << 6 | buf[2] << 1 | buf[3] >> 4; 708*17d15b25SDag-Erling Smørgrav 709*17d15b25SDag-Erling Smørgrav case 2: /* .....111 11...... ........ ........ ........ */ 710*17d15b25SDag-Erling Smørgrav /* 00000... ........ ........ ........ ........ */ 711*17d15b25SDag-Erling Smørgrav dst[0] = buf[0] << 3 | buf[1] >> 2; 712*17d15b25SDag-Erling Smørgrav 713*17d15b25SDag-Erling Smørgrav break; 714*17d15b25SDag-Erling Smørgrav 715*17d15b25SDag-Erling Smørgrav default: 716*17d15b25SDag-Erling Smørgrav return -1; 717*17d15b25SDag-Erling Smørgrav } 718*17d15b25SDag-Erling Smørgrav dst += (i + 1) / 2; 719*17d15b25SDag-Erling Smørgrav 720*17d15b25SDag-Erling Smørgrav if (check_padding) { 721*17d15b25SDag-Erling Smørgrav /* Check remaining padding characters */ 722*17d15b25SDag-Erling Smørgrav if (ch != '=') 723*17d15b25SDag-Erling Smørgrav return -1; 724*17d15b25SDag-Erling Smørgrav 725*17d15b25SDag-Erling Smørgrav /* One down, 8 - i - 1 more to come... */ 726*17d15b25SDag-Erling Smørgrav for (i = 8 - i - 1; i > 0; i--) { 727*17d15b25SDag-Erling Smørgrav 728*17d15b25SDag-Erling Smørgrav do { 729*17d15b25SDag-Erling Smørgrav if (src_sz == 0) 730*17d15b25SDag-Erling Smørgrav return -1; 731*17d15b25SDag-Erling Smørgrav ch = *src++; 732*17d15b25SDag-Erling Smørgrav src_sz--; 733*17d15b25SDag-Erling Smørgrav 734*17d15b25SDag-Erling Smørgrav } while (isspace(ch)); 735*17d15b25SDag-Erling Smørgrav 736*17d15b25SDag-Erling Smørgrav if (ch != '=') 737*17d15b25SDag-Erling Smørgrav return -1; 738*17d15b25SDag-Erling Smørgrav } 739*17d15b25SDag-Erling Smørgrav } 740*17d15b25SDag-Erling Smørgrav } 741*17d15b25SDag-Erling Smørgrav return dst - start; 742*17d15b25SDag-Erling Smørgrav } 743*17d15b25SDag-Erling Smørgrav 744*17d15b25SDag-Erling Smørgrav int 745*17d15b25SDag-Erling Smørgrav ldns_b32_pton(const char* src, size_t src_sz, uint8_t* dst, size_t dst_sz) 746*17d15b25SDag-Erling Smørgrav { 747*17d15b25SDag-Erling Smørgrav return ldns_b32_pton_base(src, src_sz, dst, dst_sz, false, true); 748*17d15b25SDag-Erling Smørgrav } 749*17d15b25SDag-Erling Smørgrav 750*17d15b25SDag-Erling Smørgrav int 751*17d15b25SDag-Erling Smørgrav ldns_b32_pton_extended_hex(const char* src, size_t src_sz, 752*17d15b25SDag-Erling Smørgrav uint8_t* dst, size_t dst_sz) 753*17d15b25SDag-Erling Smørgrav { 754*17d15b25SDag-Erling Smørgrav return ldns_b32_pton_base(src, src_sz, dst, dst_sz, true, true); 755*17d15b25SDag-Erling Smørgrav } 756*17d15b25SDag-Erling Smørgrav 757*17d15b25SDag-Erling Smørgrav #ifndef HAVE_B32_PTON 758*17d15b25SDag-Erling Smørgrav 759*17d15b25SDag-Erling Smørgrav int 760*17d15b25SDag-Erling Smørgrav b32_pton(const char* src, size_t src_sz, uint8_t* dst, size_t dst_sz) 761*17d15b25SDag-Erling Smørgrav { 762*17d15b25SDag-Erling Smørgrav return ldns_b32_pton_base(src, src_sz, dst, dst_sz, false, true); 763*17d15b25SDag-Erling Smørgrav } 764*17d15b25SDag-Erling Smørgrav 765*17d15b25SDag-Erling Smørgrav int 766*17d15b25SDag-Erling Smørgrav b32_pton_extended_hex(const char* src, size_t src_sz, 767*17d15b25SDag-Erling Smørgrav uint8_t* dst, size_t dst_sz) 768*17d15b25SDag-Erling Smørgrav { 769*17d15b25SDag-Erling Smørgrav return ldns_b32_pton_base(src, src_sz, dst, dst_sz, true, true); 770*17d15b25SDag-Erling Smørgrav } 771*17d15b25SDag-Erling Smørgrav 772*17d15b25SDag-Erling Smørgrav #endif /* ! HAVE_B32_PTON */ 773*17d15b25SDag-Erling Smørgrav 774