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> 2317d15b25SDag-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 } 46417d15b25SDag-Erling Smørgrav 46517d15b25SDag-Erling Smørgrav /* 46617d15b25SDag-Erling Smørgrav * For backwards compatibility, because we have always exported this symbol. 46717d15b25SDag-Erling Smørgrav */ 46817d15b25SDag-Erling Smørgrav #ifdef HAVE_B64_NTOP 46917d15b25SDag-Erling Smørgrav int ldns_b64_ntop(const uint8_t* src, size_t srclength, 47017d15b25SDag-Erling Smørgrav char *target, size_t targsize); 47117d15b25SDag-Erling Smørgrav { 47217d15b25SDag-Erling Smørgrav return b64_ntop(src, srclength, target, targsize); 47317d15b25SDag-Erling Smørgrav } 47417d15b25SDag-Erling Smørgrav #endif 47517d15b25SDag-Erling Smørgrav 47617d15b25SDag-Erling Smørgrav /* 47717d15b25SDag-Erling Smørgrav * For backwards compatibility, because we have always exported this symbol. 47817d15b25SDag-Erling Smørgrav */ 47917d15b25SDag-Erling Smørgrav #ifdef HAVE_B64_PTON 48017d15b25SDag-Erling Smørgrav int ldns_b64_pton(const char* src, uint8_t *target, size_t targsize) 48117d15b25SDag-Erling Smørgrav { 48217d15b25SDag-Erling Smørgrav return b64_pton(src, target, targsize); 48317d15b25SDag-Erling Smørgrav } 48417d15b25SDag-Erling Smørgrav #endif 48517d15b25SDag-Erling Smørgrav 48617d15b25SDag-Erling Smørgrav 48717d15b25SDag-Erling Smørgrav static int 48817d15b25SDag-Erling Smørgrav ldns_b32_ntop_base(const uint8_t* src, size_t src_sz, 48917d15b25SDag-Erling Smørgrav char* dst, size_t dst_sz, 49017d15b25SDag-Erling Smørgrav bool extended_hex, bool add_padding) 49117d15b25SDag-Erling Smørgrav { 49217d15b25SDag-Erling Smørgrav size_t ret_sz; 49317d15b25SDag-Erling Smørgrav const char* b32 = extended_hex ? "0123456789abcdefghijklmnopqrstuv" 49417d15b25SDag-Erling Smørgrav : "abcdefghijklmnopqrstuvwxyz234567"; 49517d15b25SDag-Erling Smørgrav 49617d15b25SDag-Erling Smørgrav size_t c = 0; /* c is used to carry partial base32 character over 49717d15b25SDag-Erling Smørgrav * byte boundaries for sizes with a remainder. 49817d15b25SDag-Erling Smørgrav * (i.e. src_sz % 5 != 0) 49917d15b25SDag-Erling Smørgrav */ 50017d15b25SDag-Erling Smørgrav 50117d15b25SDag-Erling Smørgrav ret_sz = add_padding ? ldns_b32_ntop_calculate_size(src_sz) 50217d15b25SDag-Erling Smørgrav : ldns_b32_ntop_calculate_size_no_padding(src_sz); 50317d15b25SDag-Erling Smørgrav 50417d15b25SDag-Erling Smørgrav /* Do we have enough space? */ 50517d15b25SDag-Erling Smørgrav if (dst_sz < ret_sz + 1) 50617d15b25SDag-Erling Smørgrav return -1; 50717d15b25SDag-Erling Smørgrav 50817d15b25SDag-Erling Smørgrav /* We know the size; terminate the string */ 50917d15b25SDag-Erling Smørgrav dst[ret_sz] = '\0'; 51017d15b25SDag-Erling Smørgrav 51117d15b25SDag-Erling Smørgrav /* First process all chunks of five */ 51217d15b25SDag-Erling Smørgrav while (src_sz >= 5) { 51317d15b25SDag-Erling Smørgrav /* 00000... ........ ........ ........ ........ */ 51417d15b25SDag-Erling Smørgrav dst[0] = b32[(src[0] ) >> 3]; 51517d15b25SDag-Erling Smørgrav 51617d15b25SDag-Erling Smørgrav /* .....111 11...... ........ ........ ........ */ 51717d15b25SDag-Erling Smørgrav dst[1] = b32[(src[0] & 0x07) << 2 | src[1] >> 6]; 51817d15b25SDag-Erling Smørgrav 51917d15b25SDag-Erling Smørgrav /* ........ ..22222. ........ ........ ........ */ 52017d15b25SDag-Erling Smørgrav dst[2] = b32[(src[1] & 0x3e) >> 1]; 52117d15b25SDag-Erling Smørgrav 52217d15b25SDag-Erling Smørgrav /* ........ .......3 3333.... ........ ........ */ 52317d15b25SDag-Erling Smørgrav dst[3] = b32[(src[1] & 0x01) << 4 | src[2] >> 4]; 52417d15b25SDag-Erling Smørgrav 52517d15b25SDag-Erling Smørgrav /* ........ ........ ....4444 4....... ........ */ 52617d15b25SDag-Erling Smørgrav dst[4] = b32[(src[2] & 0x0f) << 1 | src[3] >> 7]; 52717d15b25SDag-Erling Smørgrav 52817d15b25SDag-Erling Smørgrav /* ........ ........ ........ .55555.. ........ */ 52917d15b25SDag-Erling Smørgrav dst[5] = b32[(src[3] & 0x7c) >> 2]; 53017d15b25SDag-Erling Smørgrav 53117d15b25SDag-Erling Smørgrav /* ........ ........ ........ ......66 666..... */ 53217d15b25SDag-Erling Smørgrav dst[6] = b32[(src[3] & 0x03) << 3 | src[4] >> 5]; 53317d15b25SDag-Erling Smørgrav 53417d15b25SDag-Erling Smørgrav /* ........ ........ ........ ........ ...77777 */ 53517d15b25SDag-Erling Smørgrav dst[7] = b32[(src[4] & 0x1f) ]; 53617d15b25SDag-Erling Smørgrav 53717d15b25SDag-Erling Smørgrav src_sz -= 5; 53817d15b25SDag-Erling Smørgrav src += 5; 53917d15b25SDag-Erling Smørgrav dst += 8; 54017d15b25SDag-Erling Smørgrav } 54117d15b25SDag-Erling Smørgrav /* Process what remains */ 54217d15b25SDag-Erling Smørgrav switch (src_sz) { 54317d15b25SDag-Erling Smørgrav case 4: /* ........ ........ ........ ......66 666..... */ 54417d15b25SDag-Erling Smørgrav dst[6] = b32[(src[3] & 0x03) << 3]; 54517d15b25SDag-Erling Smørgrav 54617d15b25SDag-Erling Smørgrav /* ........ ........ ........ .55555.. ........ */ 54717d15b25SDag-Erling Smørgrav dst[5] = b32[(src[3] & 0x7c) >> 2]; 54817d15b25SDag-Erling Smørgrav 54917d15b25SDag-Erling Smørgrav /* ........ ........ ....4444 4....... ........ */ 55017d15b25SDag-Erling Smørgrav c = src[3] >> 7 ; 55117d15b25SDag-Erling Smørgrav case 3: dst[4] = b32[(src[2] & 0x0f) << 1 | c]; 55217d15b25SDag-Erling Smørgrav 55317d15b25SDag-Erling Smørgrav /* ........ .......3 3333.... ........ ........ */ 55417d15b25SDag-Erling Smørgrav c = src[2] >> 4 ; 55517d15b25SDag-Erling Smørgrav case 2: dst[3] = b32[(src[1] & 0x01) << 4 | c]; 55617d15b25SDag-Erling Smørgrav 55717d15b25SDag-Erling Smørgrav /* ........ ..22222. ........ ........ ........ */ 55817d15b25SDag-Erling Smørgrav dst[2] = b32[(src[1] & 0x3e) >> 1]; 55917d15b25SDag-Erling Smørgrav 56017d15b25SDag-Erling Smørgrav /* .....111 11...... ........ ........ ........ */ 56117d15b25SDag-Erling Smørgrav c = src[1] >> 6 ; 56217d15b25SDag-Erling Smørgrav case 1: dst[1] = b32[(src[0] & 0x07) << 2 | c]; 56317d15b25SDag-Erling Smørgrav 56417d15b25SDag-Erling Smørgrav /* 00000... ........ ........ ........ ........ */ 56517d15b25SDag-Erling Smørgrav dst[0] = b32[ src[0] >> 3]; 56617d15b25SDag-Erling Smørgrav } 56717d15b25SDag-Erling Smørgrav /* Add padding */ 56817d15b25SDag-Erling Smørgrav if (add_padding) { 56917d15b25SDag-Erling Smørgrav switch (src_sz) { 57017d15b25SDag-Erling Smørgrav case 1: dst[2] = '='; 57117d15b25SDag-Erling Smørgrav dst[3] = '='; 57217d15b25SDag-Erling Smørgrav case 2: dst[4] = '='; 57317d15b25SDag-Erling Smørgrav case 3: dst[5] = '='; 57417d15b25SDag-Erling Smørgrav dst[6] = '='; 57517d15b25SDag-Erling Smørgrav case 4: dst[7] = '='; 57617d15b25SDag-Erling Smørgrav } 57717d15b25SDag-Erling Smørgrav } 57817d15b25SDag-Erling Smørgrav return (int)ret_sz; 57917d15b25SDag-Erling Smørgrav } 58017d15b25SDag-Erling Smørgrav 58117d15b25SDag-Erling Smørgrav int 58217d15b25SDag-Erling Smørgrav ldns_b32_ntop(const uint8_t* src, size_t src_sz, char* dst, size_t dst_sz) 58317d15b25SDag-Erling Smørgrav { 58417d15b25SDag-Erling Smørgrav return ldns_b32_ntop_base(src, src_sz, dst, dst_sz, false, true); 58517d15b25SDag-Erling Smørgrav } 58617d15b25SDag-Erling Smørgrav 58717d15b25SDag-Erling Smørgrav int 58817d15b25SDag-Erling Smørgrav ldns_b32_ntop_extended_hex(const uint8_t* src, size_t src_sz, 58917d15b25SDag-Erling Smørgrav char* dst, size_t dst_sz) 59017d15b25SDag-Erling Smørgrav { 59117d15b25SDag-Erling Smørgrav return ldns_b32_ntop_base(src, src_sz, dst, dst_sz, true, true); 59217d15b25SDag-Erling Smørgrav } 59317d15b25SDag-Erling Smørgrav 59417d15b25SDag-Erling Smørgrav #ifndef HAVE_B32_NTOP 59517d15b25SDag-Erling Smørgrav 59617d15b25SDag-Erling Smørgrav int 59717d15b25SDag-Erling Smørgrav b32_ntop(const uint8_t* src, size_t src_sz, char* dst, size_t dst_sz) 59817d15b25SDag-Erling Smørgrav { 59917d15b25SDag-Erling Smørgrav return ldns_b32_ntop_base(src, src_sz, dst, dst_sz, false, true); 60017d15b25SDag-Erling Smørgrav } 60117d15b25SDag-Erling Smørgrav 60217d15b25SDag-Erling Smørgrav int 60317d15b25SDag-Erling Smørgrav b32_ntop_extended_hex(const uint8_t* src, size_t src_sz, 60417d15b25SDag-Erling Smørgrav char* dst, size_t dst_sz) 60517d15b25SDag-Erling Smørgrav { 60617d15b25SDag-Erling Smørgrav return ldns_b32_ntop_base(src, src_sz, dst, dst_sz, true, true); 60717d15b25SDag-Erling Smørgrav } 60817d15b25SDag-Erling Smørgrav 60917d15b25SDag-Erling Smørgrav #endif /* ! HAVE_B32_NTOP */ 61017d15b25SDag-Erling Smørgrav 61117d15b25SDag-Erling Smørgrav static int 61217d15b25SDag-Erling Smørgrav ldns_b32_pton_base(const char* src, size_t src_sz, 61317d15b25SDag-Erling Smørgrav uint8_t* dst, size_t dst_sz, 61417d15b25SDag-Erling Smørgrav bool extended_hex, bool check_padding) 61517d15b25SDag-Erling Smørgrav { 61617d15b25SDag-Erling Smørgrav size_t i = 0; 61717d15b25SDag-Erling Smørgrav char ch = '\0'; 61817d15b25SDag-Erling Smørgrav uint8_t buf[8]; 61917d15b25SDag-Erling Smørgrav uint8_t* start = dst; 62017d15b25SDag-Erling Smørgrav 62117d15b25SDag-Erling Smørgrav while (src_sz) { 62217d15b25SDag-Erling Smørgrav /* Collect 8 characters in buf (if possible) */ 62317d15b25SDag-Erling Smørgrav for (i = 0; i < 8; i++) { 62417d15b25SDag-Erling Smørgrav 62517d15b25SDag-Erling Smørgrav do { 62617d15b25SDag-Erling Smørgrav ch = *src++; 62717d15b25SDag-Erling Smørgrav --src_sz; 62817d15b25SDag-Erling Smørgrav 629*986ba33cSDag-Erling Smørgrav } while (isspace((unsigned char)ch) && src_sz > 0); 63017d15b25SDag-Erling Smørgrav 63117d15b25SDag-Erling Smørgrav if (ch == '=' || ch == '\0') 63217d15b25SDag-Erling Smørgrav break; 63317d15b25SDag-Erling Smørgrav 63417d15b25SDag-Erling Smørgrav else if (extended_hex) 63517d15b25SDag-Erling Smørgrav 63617d15b25SDag-Erling Smørgrav if (ch >= '0' && ch <= '9') 63717d15b25SDag-Erling Smørgrav buf[i] = (uint8_t)ch - '0'; 63817d15b25SDag-Erling Smørgrav else if (ch >= 'a' && ch <= 'v') 63917d15b25SDag-Erling Smørgrav buf[i] = (uint8_t)ch - 'a' + 10; 64017d15b25SDag-Erling Smørgrav else if (ch >= 'A' && ch <= 'V') 64117d15b25SDag-Erling Smørgrav buf[i] = (uint8_t)ch - 'A' + 10; 64217d15b25SDag-Erling Smørgrav else 64317d15b25SDag-Erling Smørgrav return -1; 64417d15b25SDag-Erling Smørgrav 64517d15b25SDag-Erling Smørgrav else if (ch >= 'a' && ch <= 'z') 64617d15b25SDag-Erling Smørgrav buf[i] = (uint8_t)ch - 'a'; 64717d15b25SDag-Erling Smørgrav else if (ch >= 'A' && ch <= 'Z') 64817d15b25SDag-Erling Smørgrav buf[i] = (uint8_t)ch - 'A'; 64917d15b25SDag-Erling Smørgrav else if (ch >= '2' && ch <= '7') 65017d15b25SDag-Erling Smørgrav buf[i] = (uint8_t)ch - '2' + 26; 65117d15b25SDag-Erling Smørgrav else 65217d15b25SDag-Erling Smørgrav return -1; 65317d15b25SDag-Erling Smørgrav } 65417d15b25SDag-Erling Smørgrav /* Less that 8 characters. We're done. */ 65517d15b25SDag-Erling Smørgrav if (i < 8) 65617d15b25SDag-Erling Smørgrav break; 65717d15b25SDag-Erling Smørgrav 65817d15b25SDag-Erling Smørgrav /* Enough space available at the destination? */ 65917d15b25SDag-Erling Smørgrav if (dst_sz < 5) 66017d15b25SDag-Erling Smørgrav return -1; 66117d15b25SDag-Erling Smørgrav 66217d15b25SDag-Erling Smørgrav /* 00000... ........ ........ ........ ........ */ 66317d15b25SDag-Erling Smørgrav /* .....111 11...... ........ ........ ........ */ 66417d15b25SDag-Erling Smørgrav dst[0] = buf[0] << 3 | buf[1] >> 2; 66517d15b25SDag-Erling Smørgrav 66617d15b25SDag-Erling Smørgrav /* .....111 11...... ........ ........ ........ */ 66717d15b25SDag-Erling Smørgrav /* ........ ..22222. ........ ........ ........ */ 66817d15b25SDag-Erling Smørgrav /* ........ .......3 3333.... ........ ........ */ 66917d15b25SDag-Erling Smørgrav dst[1] = buf[1] << 6 | buf[2] << 1 | buf[3] >> 4; 67017d15b25SDag-Erling Smørgrav 67117d15b25SDag-Erling Smørgrav /* ........ .......3 3333.... ........ ........ */ 67217d15b25SDag-Erling Smørgrav /* ........ ........ ....4444 4....... ........ */ 67317d15b25SDag-Erling Smørgrav dst[2] = buf[3] << 4 | buf[4] >> 1; 67417d15b25SDag-Erling Smørgrav 67517d15b25SDag-Erling Smørgrav /* ........ ........ ....4444 4....... ........ */ 67617d15b25SDag-Erling Smørgrav /* ........ ........ ........ .55555.. ........ */ 67717d15b25SDag-Erling Smørgrav /* ........ ........ ........ ......66 666..... */ 67817d15b25SDag-Erling Smørgrav dst[3] = buf[4] << 7 | buf[5] << 2 | buf[6] >> 3; 67917d15b25SDag-Erling Smørgrav 68017d15b25SDag-Erling Smørgrav /* ........ ........ ........ ......66 666..... */ 68117d15b25SDag-Erling Smørgrav /* ........ ........ ........ ........ ...77777 */ 68217d15b25SDag-Erling Smørgrav dst[4] = buf[6] << 5 | buf[7]; 68317d15b25SDag-Erling Smørgrav 68417d15b25SDag-Erling Smørgrav dst += 5; 68517d15b25SDag-Erling Smørgrav dst_sz -= 5; 68617d15b25SDag-Erling Smørgrav } 68717d15b25SDag-Erling Smørgrav /* Not ending on a eight byte boundary? */ 68817d15b25SDag-Erling Smørgrav if (i > 0 && i < 8) { 68917d15b25SDag-Erling Smørgrav 69017d15b25SDag-Erling Smørgrav /* Enough space available at the destination? */ 69117d15b25SDag-Erling Smørgrav if (dst_sz < (i + 1) / 2) 69217d15b25SDag-Erling Smørgrav return -1; 69317d15b25SDag-Erling Smørgrav 69417d15b25SDag-Erling Smørgrav switch (i) { 69517d15b25SDag-Erling Smørgrav case 7: /* ........ ........ ........ ......66 666..... */ 69617d15b25SDag-Erling Smørgrav /* ........ ........ ........ .55555.. ........ */ 69717d15b25SDag-Erling Smørgrav /* ........ ........ ....4444 4....... ........ */ 69817d15b25SDag-Erling Smørgrav dst[3] = buf[4] << 7 | buf[5] << 2 | buf[6] >> 3; 69917d15b25SDag-Erling Smørgrav 70017d15b25SDag-Erling Smørgrav case 5: /* ........ ........ ....4444 4....... ........ */ 70117d15b25SDag-Erling Smørgrav /* ........ .......3 3333.... ........ ........ */ 70217d15b25SDag-Erling Smørgrav dst[2] = buf[3] << 4 | buf[4] >> 1; 70317d15b25SDag-Erling Smørgrav 70417d15b25SDag-Erling Smørgrav case 4: /* ........ .......3 3333.... ........ ........ */ 70517d15b25SDag-Erling Smørgrav /* ........ ..22222. ........ ........ ........ */ 70617d15b25SDag-Erling Smørgrav /* .....111 11...... ........ ........ ........ */ 70717d15b25SDag-Erling Smørgrav dst[1] = buf[1] << 6 | buf[2] << 1 | buf[3] >> 4; 70817d15b25SDag-Erling Smørgrav 70917d15b25SDag-Erling Smørgrav case 2: /* .....111 11...... ........ ........ ........ */ 71017d15b25SDag-Erling Smørgrav /* 00000... ........ ........ ........ ........ */ 71117d15b25SDag-Erling Smørgrav dst[0] = buf[0] << 3 | buf[1] >> 2; 71217d15b25SDag-Erling Smørgrav 71317d15b25SDag-Erling Smørgrav break; 71417d15b25SDag-Erling Smørgrav 71517d15b25SDag-Erling Smørgrav default: 71617d15b25SDag-Erling Smørgrav return -1; 71717d15b25SDag-Erling Smørgrav } 71817d15b25SDag-Erling Smørgrav dst += (i + 1) / 2; 71917d15b25SDag-Erling Smørgrav 72017d15b25SDag-Erling Smørgrav if (check_padding) { 72117d15b25SDag-Erling Smørgrav /* Check remaining padding characters */ 72217d15b25SDag-Erling Smørgrav if (ch != '=') 72317d15b25SDag-Erling Smørgrav return -1; 72417d15b25SDag-Erling Smørgrav 72517d15b25SDag-Erling Smørgrav /* One down, 8 - i - 1 more to come... */ 72617d15b25SDag-Erling Smørgrav for (i = 8 - i - 1; i > 0; i--) { 72717d15b25SDag-Erling Smørgrav 72817d15b25SDag-Erling Smørgrav do { 72917d15b25SDag-Erling Smørgrav if (src_sz == 0) 73017d15b25SDag-Erling Smørgrav return -1; 73117d15b25SDag-Erling Smørgrav ch = *src++; 73217d15b25SDag-Erling Smørgrav src_sz--; 73317d15b25SDag-Erling Smørgrav 734*986ba33cSDag-Erling Smørgrav } while (isspace((unsigned char)ch)); 73517d15b25SDag-Erling Smørgrav 73617d15b25SDag-Erling Smørgrav if (ch != '=') 73717d15b25SDag-Erling Smørgrav return -1; 73817d15b25SDag-Erling Smørgrav } 73917d15b25SDag-Erling Smørgrav } 74017d15b25SDag-Erling Smørgrav } 74117d15b25SDag-Erling Smørgrav return dst - start; 74217d15b25SDag-Erling Smørgrav } 74317d15b25SDag-Erling Smørgrav 74417d15b25SDag-Erling Smørgrav int 74517d15b25SDag-Erling Smørgrav ldns_b32_pton(const char* src, size_t src_sz, uint8_t* dst, size_t dst_sz) 74617d15b25SDag-Erling Smørgrav { 74717d15b25SDag-Erling Smørgrav return ldns_b32_pton_base(src, src_sz, dst, dst_sz, false, true); 74817d15b25SDag-Erling Smørgrav } 74917d15b25SDag-Erling Smørgrav 75017d15b25SDag-Erling Smørgrav int 75117d15b25SDag-Erling Smørgrav ldns_b32_pton_extended_hex(const char* src, size_t src_sz, 75217d15b25SDag-Erling Smørgrav uint8_t* dst, size_t dst_sz) 75317d15b25SDag-Erling Smørgrav { 75417d15b25SDag-Erling Smørgrav return ldns_b32_pton_base(src, src_sz, dst, dst_sz, true, true); 75517d15b25SDag-Erling Smørgrav } 75617d15b25SDag-Erling Smørgrav 75717d15b25SDag-Erling Smørgrav #ifndef HAVE_B32_PTON 75817d15b25SDag-Erling Smørgrav 75917d15b25SDag-Erling Smørgrav int 76017d15b25SDag-Erling Smørgrav b32_pton(const char* src, size_t src_sz, uint8_t* dst, size_t dst_sz) 76117d15b25SDag-Erling Smørgrav { 76217d15b25SDag-Erling Smørgrav return ldns_b32_pton_base(src, src_sz, dst, dst_sz, false, true); 76317d15b25SDag-Erling Smørgrav } 76417d15b25SDag-Erling Smørgrav 76517d15b25SDag-Erling Smørgrav int 76617d15b25SDag-Erling Smørgrav b32_pton_extended_hex(const char* src, size_t src_sz, 76717d15b25SDag-Erling Smørgrav uint8_t* dst, size_t dst_sz) 76817d15b25SDag-Erling Smørgrav { 76917d15b25SDag-Erling Smørgrav return ldns_b32_pton_base(src, src_sz, dst, dst_sz, true, true); 77017d15b25SDag-Erling Smørgrav } 77117d15b25SDag-Erling Smørgrav 77217d15b25SDag-Erling Smørgrav #endif /* ! HAVE_B32_PTON */ 77317d15b25SDag-Erling Smørgrav 774