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> 237b5038d7SDag-Erling Smørgrav 247b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL 257b5038d7SDag-Erling Smørgrav #include <openssl/rand.h> 267b5038d7SDag-Erling Smørgrav #endif 277b5038d7SDag-Erling Smørgrav 287b5038d7SDag-Erling Smørgrav /* put this here tmp. for debugging */ 297b5038d7SDag-Erling Smørgrav static void 307b5038d7SDag-Erling Smørgrav xprintf_rdf(ldns_rdf *rd) 317b5038d7SDag-Erling Smørgrav { 327b5038d7SDag-Erling Smørgrav /* assume printable string */ 337b5038d7SDag-Erling Smørgrav fprintf(stderr, "size\t:%u\n", (unsigned int)ldns_rdf_size(rd)); 347b5038d7SDag-Erling Smørgrav fprintf(stderr, "type\t:%u\n", (unsigned int)ldns_rdf_get_type(rd)); 357b5038d7SDag-Erling Smørgrav fprintf(stderr, "data\t:[%.*s]\n", (int)ldns_rdf_size(rd), 367b5038d7SDag-Erling Smørgrav (char*)ldns_rdf_data(rd)); 377b5038d7SDag-Erling Smørgrav } 387b5038d7SDag-Erling Smørgrav 397b5038d7SDag-Erling Smørgrav static void 407b5038d7SDag-Erling Smørgrav xprintf_rr(ldns_rr *rr) 417b5038d7SDag-Erling Smørgrav { 427b5038d7SDag-Erling Smørgrav /* assume printable string */ 437b5038d7SDag-Erling Smørgrav uint16_t count, i; 447b5038d7SDag-Erling Smørgrav 457b5038d7SDag-Erling Smørgrav count = ldns_rr_rd_count(rr); 467b5038d7SDag-Erling Smørgrav 477b5038d7SDag-Erling Smørgrav for(i = 0; i < count; i++) { 487b5038d7SDag-Erling Smørgrav fprintf(stderr, "print rd %u\n", (unsigned int) i); 497b5038d7SDag-Erling Smørgrav xprintf_rdf(rr->_rdata_fields[i]); 507b5038d7SDag-Erling Smørgrav } 517b5038d7SDag-Erling Smørgrav } 527b5038d7SDag-Erling Smørgrav 537b5038d7SDag-Erling Smørgrav static void 547b5038d7SDag-Erling Smørgrav xprintf_hex(uint8_t *data, size_t len) 557b5038d7SDag-Erling Smørgrav { 567b5038d7SDag-Erling Smørgrav size_t i; 577b5038d7SDag-Erling Smørgrav for (i = 0; i < len; i++) { 587b5038d7SDag-Erling Smørgrav if (i > 0 && i % 20 == 0) { 597b5038d7SDag-Erling Smørgrav printf("\t; %u - %u\n", (unsigned int) i - 19, (unsigned int) i); 607b5038d7SDag-Erling Smørgrav } 617b5038d7SDag-Erling Smørgrav printf("%02x ", (unsigned int) data[i]); 627b5038d7SDag-Erling Smørgrav } 637b5038d7SDag-Erling Smørgrav printf("\n"); 647b5038d7SDag-Erling Smørgrav } 657b5038d7SDag-Erling Smørgrav 667b5038d7SDag-Erling Smørgrav ldns_lookup_table * 677b5038d7SDag-Erling Smørgrav ldns_lookup_by_name(ldns_lookup_table *table, const char *name) 687b5038d7SDag-Erling Smørgrav { 697b5038d7SDag-Erling Smørgrav while (table->name != NULL) { 707b5038d7SDag-Erling Smørgrav if (strcasecmp(name, table->name) == 0) 717b5038d7SDag-Erling Smørgrav return table; 727b5038d7SDag-Erling Smørgrav table++; 737b5038d7SDag-Erling Smørgrav } 747b5038d7SDag-Erling Smørgrav return NULL; 757b5038d7SDag-Erling Smørgrav } 767b5038d7SDag-Erling Smørgrav 777b5038d7SDag-Erling Smørgrav ldns_lookup_table * 787b5038d7SDag-Erling Smørgrav ldns_lookup_by_id(ldns_lookup_table *table, int id) 797b5038d7SDag-Erling Smørgrav { 807b5038d7SDag-Erling Smørgrav while (table->name != NULL) { 817b5038d7SDag-Erling Smørgrav if (table->id == id) 827b5038d7SDag-Erling Smørgrav return table; 837b5038d7SDag-Erling Smørgrav table++; 847b5038d7SDag-Erling Smørgrav } 857b5038d7SDag-Erling Smørgrav return NULL; 867b5038d7SDag-Erling Smørgrav } 877b5038d7SDag-Erling Smørgrav 887b5038d7SDag-Erling Smørgrav int 897b5038d7SDag-Erling Smørgrav ldns_get_bit(uint8_t bits[], size_t index) 907b5038d7SDag-Erling Smørgrav { 917b5038d7SDag-Erling Smørgrav /* 927b5038d7SDag-Erling Smørgrav * The bits are counted from left to right, so bit #0 is the 937b5038d7SDag-Erling Smørgrav * left most bit. 947b5038d7SDag-Erling Smørgrav */ 957b5038d7SDag-Erling Smørgrav return (int) (bits[index / 8] & (1 << (7 - index % 8))); 967b5038d7SDag-Erling Smørgrav } 977b5038d7SDag-Erling Smørgrav 987b5038d7SDag-Erling Smørgrav int 997b5038d7SDag-Erling Smørgrav ldns_get_bit_r(uint8_t bits[], size_t index) 1007b5038d7SDag-Erling Smørgrav { 1017b5038d7SDag-Erling Smørgrav /* 1027b5038d7SDag-Erling Smørgrav * The bits are counted from right to left, so bit #0 is the 1037b5038d7SDag-Erling Smørgrav * right most bit. 1047b5038d7SDag-Erling Smørgrav */ 1057b5038d7SDag-Erling Smørgrav return (int) bits[index / 8] & (1 << (index % 8)); 1067b5038d7SDag-Erling Smørgrav } 1077b5038d7SDag-Erling Smørgrav 1087b5038d7SDag-Erling Smørgrav void 1097b5038d7SDag-Erling Smørgrav ldns_set_bit(uint8_t *byte, int bit_nr, bool value) 1107b5038d7SDag-Erling Smørgrav { 1117b5038d7SDag-Erling Smørgrav /* 1127b5038d7SDag-Erling Smørgrav * The bits are counted from right to left, so bit #0 is the 1137b5038d7SDag-Erling Smørgrav * right most bit. 1147b5038d7SDag-Erling Smørgrav */ 1157b5038d7SDag-Erling Smørgrav if (bit_nr >= 0 && bit_nr < 8) { 1167b5038d7SDag-Erling Smørgrav if (value) { 1177b5038d7SDag-Erling Smørgrav *byte = *byte | (0x01 << bit_nr); 1187b5038d7SDag-Erling Smørgrav } else { 1197b5038d7SDag-Erling Smørgrav *byte = *byte & ~(0x01 << bit_nr); 1207b5038d7SDag-Erling Smørgrav } 1217b5038d7SDag-Erling Smørgrav } 1227b5038d7SDag-Erling Smørgrav } 1237b5038d7SDag-Erling Smørgrav 1247b5038d7SDag-Erling Smørgrav int 1257b5038d7SDag-Erling Smørgrav ldns_hexdigit_to_int(char ch) 1267b5038d7SDag-Erling Smørgrav { 1277b5038d7SDag-Erling Smørgrav switch (ch) { 1287b5038d7SDag-Erling Smørgrav case '0': return 0; 1297b5038d7SDag-Erling Smørgrav case '1': return 1; 1307b5038d7SDag-Erling Smørgrav case '2': return 2; 1317b5038d7SDag-Erling Smørgrav case '3': return 3; 1327b5038d7SDag-Erling Smørgrav case '4': return 4; 1337b5038d7SDag-Erling Smørgrav case '5': return 5; 1347b5038d7SDag-Erling Smørgrav case '6': return 6; 1357b5038d7SDag-Erling Smørgrav case '7': return 7; 1367b5038d7SDag-Erling Smørgrav case '8': return 8; 1377b5038d7SDag-Erling Smørgrav case '9': return 9; 1387b5038d7SDag-Erling Smørgrav case 'a': case 'A': return 10; 1397b5038d7SDag-Erling Smørgrav case 'b': case 'B': return 11; 1407b5038d7SDag-Erling Smørgrav case 'c': case 'C': return 12; 1417b5038d7SDag-Erling Smørgrav case 'd': case 'D': return 13; 1427b5038d7SDag-Erling Smørgrav case 'e': case 'E': return 14; 1437b5038d7SDag-Erling Smørgrav case 'f': case 'F': return 15; 1447b5038d7SDag-Erling Smørgrav default: 1457b5038d7SDag-Erling Smørgrav return -1; 1467b5038d7SDag-Erling Smørgrav } 1477b5038d7SDag-Erling Smørgrav } 1487b5038d7SDag-Erling Smørgrav 1497b5038d7SDag-Erling Smørgrav char 1507b5038d7SDag-Erling Smørgrav ldns_int_to_hexdigit(int i) 1517b5038d7SDag-Erling Smørgrav { 1527b5038d7SDag-Erling Smørgrav switch (i) { 1537b5038d7SDag-Erling Smørgrav case 0: return '0'; 1547b5038d7SDag-Erling Smørgrav case 1: return '1'; 1557b5038d7SDag-Erling Smørgrav case 2: return '2'; 1567b5038d7SDag-Erling Smørgrav case 3: return '3'; 1577b5038d7SDag-Erling Smørgrav case 4: return '4'; 1587b5038d7SDag-Erling Smørgrav case 5: return '5'; 1597b5038d7SDag-Erling Smørgrav case 6: return '6'; 1607b5038d7SDag-Erling Smørgrav case 7: return '7'; 1617b5038d7SDag-Erling Smørgrav case 8: return '8'; 1627b5038d7SDag-Erling Smørgrav case 9: return '9'; 1637b5038d7SDag-Erling Smørgrav case 10: return 'a'; 1647b5038d7SDag-Erling Smørgrav case 11: return 'b'; 1657b5038d7SDag-Erling Smørgrav case 12: return 'c'; 1667b5038d7SDag-Erling Smørgrav case 13: return 'd'; 1677b5038d7SDag-Erling Smørgrav case 14: return 'e'; 1687b5038d7SDag-Erling Smørgrav case 15: return 'f'; 1697b5038d7SDag-Erling Smørgrav default: 1707b5038d7SDag-Erling Smørgrav abort(); 1717b5038d7SDag-Erling Smørgrav } 1727b5038d7SDag-Erling Smørgrav } 1737b5038d7SDag-Erling Smørgrav 1747b5038d7SDag-Erling Smørgrav int 1757b5038d7SDag-Erling Smørgrav ldns_hexstring_to_data(uint8_t *data, const char *str) 1767b5038d7SDag-Erling Smørgrav { 1777b5038d7SDag-Erling Smørgrav size_t i; 1787b5038d7SDag-Erling Smørgrav 1797b5038d7SDag-Erling Smørgrav if (!str || !data) { 1807b5038d7SDag-Erling Smørgrav return -1; 1817b5038d7SDag-Erling Smørgrav } 1827b5038d7SDag-Erling Smørgrav 1837b5038d7SDag-Erling Smørgrav if (strlen(str) % 2 != 0) { 1847b5038d7SDag-Erling Smørgrav return -2; 1857b5038d7SDag-Erling Smørgrav } 1867b5038d7SDag-Erling Smørgrav 1877b5038d7SDag-Erling Smørgrav for (i = 0; i < strlen(str) / 2; i++) { 1887b5038d7SDag-Erling Smørgrav data[i] = 1897b5038d7SDag-Erling Smørgrav 16 * (uint8_t) ldns_hexdigit_to_int(str[i*2]) + 1907b5038d7SDag-Erling Smørgrav (uint8_t) ldns_hexdigit_to_int(str[i*2 + 1]); 1917b5038d7SDag-Erling Smørgrav } 1927b5038d7SDag-Erling Smørgrav 1937b5038d7SDag-Erling Smørgrav return (int) i; 1947b5038d7SDag-Erling Smørgrav } 1957b5038d7SDag-Erling Smørgrav 1967b5038d7SDag-Erling Smørgrav const char * 1977b5038d7SDag-Erling Smørgrav ldns_version(void) 1987b5038d7SDag-Erling Smørgrav { 1997b5038d7SDag-Erling Smørgrav return (char*)LDNS_VERSION; 2007b5038d7SDag-Erling Smørgrav } 2017b5038d7SDag-Erling Smørgrav 2027b5038d7SDag-Erling Smørgrav /* Number of days per month (except for February in leap years). */ 2037b5038d7SDag-Erling Smørgrav static const int mdays[] = { 2047b5038d7SDag-Erling Smørgrav 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 2057b5038d7SDag-Erling Smørgrav }; 2067b5038d7SDag-Erling Smørgrav 2077b5038d7SDag-Erling Smørgrav #define LDNS_MOD(x,y) (((x) % (y) < 0) ? ((x) % (y) + (y)) : ((x) % (y))) 2087b5038d7SDag-Erling Smørgrav #define LDNS_DIV(x,y) (((x) % (y) < 0) ? ((x) / (y) - 1 ) : ((x) / (y))) 2097b5038d7SDag-Erling Smørgrav 2107b5038d7SDag-Erling Smørgrav static int 2117b5038d7SDag-Erling Smørgrav is_leap_year(int year) 2127b5038d7SDag-Erling Smørgrav { 2137b5038d7SDag-Erling Smørgrav return LDNS_MOD(year, 4) == 0 && (LDNS_MOD(year, 100) != 0 2147b5038d7SDag-Erling Smørgrav || LDNS_MOD(year, 400) == 0); 2157b5038d7SDag-Erling Smørgrav } 2167b5038d7SDag-Erling Smørgrav 2177b5038d7SDag-Erling Smørgrav static int 2187b5038d7SDag-Erling Smørgrav leap_days(int y1, int y2) 2197b5038d7SDag-Erling Smørgrav { 2207b5038d7SDag-Erling Smørgrav --y1; 2217b5038d7SDag-Erling Smørgrav --y2; 2227b5038d7SDag-Erling Smørgrav return (LDNS_DIV(y2, 4) - LDNS_DIV(y1, 4)) - 2237b5038d7SDag-Erling Smørgrav (LDNS_DIV(y2, 100) - LDNS_DIV(y1, 100)) + 2247b5038d7SDag-Erling Smørgrav (LDNS_DIV(y2, 400) - LDNS_DIV(y1, 400)); 2257b5038d7SDag-Erling Smørgrav } 2267b5038d7SDag-Erling Smørgrav 2277b5038d7SDag-Erling Smørgrav /* 2287b5038d7SDag-Erling Smørgrav * Code adapted from Python 2.4.1 sources (Lib/calendar.py). 2297b5038d7SDag-Erling Smørgrav */ 2307b5038d7SDag-Erling Smørgrav time_t 231*2787e39aSDag-Erling Smørgrav ldns_mktime_from_utc(const struct tm *tm) 2327b5038d7SDag-Erling Smørgrav { 2337b5038d7SDag-Erling Smørgrav int year = 1900 + tm->tm_year; 2347b5038d7SDag-Erling Smørgrav time_t days = 365 * ((time_t) year - 1970) + leap_days(1970, year); 2357b5038d7SDag-Erling Smørgrav time_t hours; 2367b5038d7SDag-Erling Smørgrav time_t minutes; 2377b5038d7SDag-Erling Smørgrav time_t seconds; 2387b5038d7SDag-Erling Smørgrav int i; 2397b5038d7SDag-Erling Smørgrav 2407b5038d7SDag-Erling Smørgrav for (i = 0; i < tm->tm_mon; ++i) { 2417b5038d7SDag-Erling Smørgrav days += mdays[i]; 2427b5038d7SDag-Erling Smørgrav } 2437b5038d7SDag-Erling Smørgrav if (tm->tm_mon > 1 && is_leap_year(year)) { 2447b5038d7SDag-Erling Smørgrav ++days; 2457b5038d7SDag-Erling Smørgrav } 2467b5038d7SDag-Erling Smørgrav days += tm->tm_mday - 1; 2477b5038d7SDag-Erling Smørgrav 2487b5038d7SDag-Erling Smørgrav hours = days * 24 + tm->tm_hour; 2497b5038d7SDag-Erling Smørgrav minutes = hours * 60 + tm->tm_min; 2507b5038d7SDag-Erling Smørgrav seconds = minutes * 60 + tm->tm_sec; 2517b5038d7SDag-Erling Smørgrav 2527b5038d7SDag-Erling Smørgrav return seconds; 2537b5038d7SDag-Erling Smørgrav } 2547b5038d7SDag-Erling Smørgrav 255*2787e39aSDag-Erling Smørgrav time_t 256*2787e39aSDag-Erling Smørgrav mktime_from_utc(const struct tm *tm) 257*2787e39aSDag-Erling Smørgrav { 258*2787e39aSDag-Erling Smørgrav return ldns_mktime_from_utc(tm); 259*2787e39aSDag-Erling Smørgrav } 260*2787e39aSDag-Erling Smørgrav 2617b5038d7SDag-Erling Smørgrav #if SIZEOF_TIME_T <= 4 2627b5038d7SDag-Erling Smørgrav 2637b5038d7SDag-Erling Smørgrav static void 2647b5038d7SDag-Erling Smørgrav ldns_year_and_yday_from_days_since_epoch(int64_t days, struct tm *result) 2657b5038d7SDag-Erling Smørgrav { 2667b5038d7SDag-Erling Smørgrav int year = 1970; 2677b5038d7SDag-Erling Smørgrav int new_year; 2687b5038d7SDag-Erling Smørgrav 2697b5038d7SDag-Erling Smørgrav while (days < 0 || days >= (int64_t) (is_leap_year(year) ? 366 : 365)) { 2707b5038d7SDag-Erling Smørgrav new_year = year + (int) LDNS_DIV(days, 365); 2717b5038d7SDag-Erling Smørgrav days -= (new_year - year) * 365; 2727b5038d7SDag-Erling Smørgrav days -= leap_days(year, new_year); 2737b5038d7SDag-Erling Smørgrav year = new_year; 2747b5038d7SDag-Erling Smørgrav } 2757b5038d7SDag-Erling Smørgrav result->tm_year = year; 2767b5038d7SDag-Erling Smørgrav result->tm_yday = (int) days; 2777b5038d7SDag-Erling Smørgrav } 2787b5038d7SDag-Erling Smørgrav 2797b5038d7SDag-Erling Smørgrav /* Number of days per month in a leap year. */ 2807b5038d7SDag-Erling Smørgrav static const int leap_year_mdays[] = { 2817b5038d7SDag-Erling Smørgrav 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 2827b5038d7SDag-Erling Smørgrav }; 2837b5038d7SDag-Erling Smørgrav 2847b5038d7SDag-Erling Smørgrav static void 2857b5038d7SDag-Erling Smørgrav ldns_mon_and_mday_from_year_and_yday(struct tm *result) 2867b5038d7SDag-Erling Smørgrav { 2877b5038d7SDag-Erling Smørgrav int idays = result->tm_yday; 2887b5038d7SDag-Erling Smørgrav const int *mon_lengths = is_leap_year(result->tm_year) ? 2897b5038d7SDag-Erling Smørgrav leap_year_mdays : mdays; 2907b5038d7SDag-Erling Smørgrav 2917b5038d7SDag-Erling Smørgrav result->tm_mon = 0; 2927b5038d7SDag-Erling Smørgrav while (idays >= mon_lengths[result->tm_mon]) { 2937b5038d7SDag-Erling Smørgrav idays -= mon_lengths[result->tm_mon++]; 2947b5038d7SDag-Erling Smørgrav } 2957b5038d7SDag-Erling Smørgrav result->tm_mday = idays + 1; 2967b5038d7SDag-Erling Smørgrav } 2977b5038d7SDag-Erling Smørgrav 2987b5038d7SDag-Erling Smørgrav static void 2997b5038d7SDag-Erling Smørgrav ldns_wday_from_year_and_yday(struct tm *result) 3007b5038d7SDag-Erling Smørgrav { 3017b5038d7SDag-Erling Smørgrav result->tm_wday = 4 /* 1-1-1970 was a thursday */ 3027b5038d7SDag-Erling Smørgrav + LDNS_MOD((result->tm_year - 1970), 7) * LDNS_MOD(365, 7) 3037b5038d7SDag-Erling Smørgrav + leap_days(1970, result->tm_year) 3047b5038d7SDag-Erling Smørgrav + result->tm_yday; 3057b5038d7SDag-Erling Smørgrav result->tm_wday = LDNS_MOD(result->tm_wday, 7); 3067b5038d7SDag-Erling Smørgrav if (result->tm_wday < 0) { 3077b5038d7SDag-Erling Smørgrav result->tm_wday += 7; 3087b5038d7SDag-Erling Smørgrav } 3097b5038d7SDag-Erling Smørgrav } 3107b5038d7SDag-Erling Smørgrav 3117b5038d7SDag-Erling Smørgrav static struct tm * 3127b5038d7SDag-Erling Smørgrav ldns_gmtime64_r(int64_t clock, struct tm *result) 3137b5038d7SDag-Erling Smørgrav { 3147b5038d7SDag-Erling Smørgrav result->tm_isdst = 0; 3157b5038d7SDag-Erling Smørgrav result->tm_sec = (int) LDNS_MOD(clock, 60); 3167b5038d7SDag-Erling Smørgrav clock = LDNS_DIV(clock, 60); 3177b5038d7SDag-Erling Smørgrav result->tm_min = (int) LDNS_MOD(clock, 60); 3187b5038d7SDag-Erling Smørgrav clock = LDNS_DIV(clock, 60); 3197b5038d7SDag-Erling Smørgrav result->tm_hour = (int) LDNS_MOD(clock, 24); 3207b5038d7SDag-Erling Smørgrav clock = LDNS_DIV(clock, 24); 3217b5038d7SDag-Erling Smørgrav 3227b5038d7SDag-Erling Smørgrav ldns_year_and_yday_from_days_since_epoch(clock, result); 3237b5038d7SDag-Erling Smørgrav ldns_mon_and_mday_from_year_and_yday(result); 3247b5038d7SDag-Erling Smørgrav ldns_wday_from_year_and_yday(result); 3257b5038d7SDag-Erling Smørgrav result->tm_year -= 1900; 3267b5038d7SDag-Erling Smørgrav 3277b5038d7SDag-Erling Smørgrav return result; 3287b5038d7SDag-Erling Smørgrav } 3297b5038d7SDag-Erling Smørgrav 3307b5038d7SDag-Erling Smørgrav #endif /* SIZEOF_TIME_T <= 4 */ 3317b5038d7SDag-Erling Smørgrav 3327b5038d7SDag-Erling Smørgrav static int64_t 3337b5038d7SDag-Erling Smørgrav ldns_serial_arithmitics_time(int32_t time, time_t now) 3347b5038d7SDag-Erling Smørgrav { 3357b5038d7SDag-Erling Smørgrav int32_t offset = time - (int32_t) now; 3367b5038d7SDag-Erling Smørgrav return (int64_t) now + offset; 3377b5038d7SDag-Erling Smørgrav } 3387b5038d7SDag-Erling Smørgrav 3397b5038d7SDag-Erling Smørgrav 3407b5038d7SDag-Erling Smørgrav struct tm * 3417b5038d7SDag-Erling Smørgrav ldns_serial_arithmitics_gmtime_r(int32_t time, time_t now, struct tm *result) 3427b5038d7SDag-Erling Smørgrav { 3437b5038d7SDag-Erling Smørgrav #if SIZEOF_TIME_T <= 4 3447b5038d7SDag-Erling Smørgrav int64_t secs_since_epoch = ldns_serial_arithmitics_time(time, now); 3457b5038d7SDag-Erling Smørgrav return ldns_gmtime64_r(secs_since_epoch, result); 3467b5038d7SDag-Erling Smørgrav #else 3477b5038d7SDag-Erling Smørgrav time_t secs_since_epoch = ldns_serial_arithmitics_time(time, now); 3487b5038d7SDag-Erling Smørgrav return gmtime_r(&secs_since_epoch, result); 3497b5038d7SDag-Erling Smørgrav #endif 3507b5038d7SDag-Erling Smørgrav } 3517b5038d7SDag-Erling Smørgrav 3527b5038d7SDag-Erling Smørgrav /** 3537b5038d7SDag-Erling Smørgrav * Init the random source 3547b5038d7SDag-Erling Smørgrav * applications should call this if they need entropy data within ldns 3557b5038d7SDag-Erling Smørgrav * If openSSL is available, it is automatically seeded from /dev/urandom 3567b5038d7SDag-Erling Smørgrav * or /dev/random 3577b5038d7SDag-Erling Smørgrav * 3587b5038d7SDag-Erling Smørgrav * If you need more entropy, or have no openssl available, this function 3597b5038d7SDag-Erling Smørgrav * MUST be called at the start of the program 3607b5038d7SDag-Erling Smørgrav * 3617b5038d7SDag-Erling Smørgrav * If openssl *is* available, this function just adds more entropy 3627b5038d7SDag-Erling Smørgrav **/ 3637b5038d7SDag-Erling Smørgrav int 3647b5038d7SDag-Erling Smørgrav ldns_init_random(FILE *fd, unsigned int size) 3657b5038d7SDag-Erling Smørgrav { 3667b5038d7SDag-Erling Smørgrav /* if fp is given, seed srandom with data from file 3677b5038d7SDag-Erling Smørgrav otherwise use /dev/urandom */ 3687b5038d7SDag-Erling Smørgrav FILE *rand_f; 3697b5038d7SDag-Erling Smørgrav uint8_t *seed; 3707b5038d7SDag-Erling Smørgrav size_t read = 0; 3717b5038d7SDag-Erling Smørgrav unsigned int seed_i; 3727b5038d7SDag-Erling Smørgrav struct timeval tv; 3737b5038d7SDag-Erling Smørgrav 3747b5038d7SDag-Erling Smørgrav /* we'll need at least sizeof(unsigned int) bytes for the 3757b5038d7SDag-Erling Smørgrav standard prng seed */ 3767b5038d7SDag-Erling Smørgrav if (size < (unsigned int) sizeof(seed_i)){ 3777b5038d7SDag-Erling Smørgrav size = (unsigned int) sizeof(seed_i); 3787b5038d7SDag-Erling Smørgrav } 3797b5038d7SDag-Erling Smørgrav 3807b5038d7SDag-Erling Smørgrav seed = LDNS_XMALLOC(uint8_t, size); 3817b5038d7SDag-Erling Smørgrav if(!seed) { 3827b5038d7SDag-Erling Smørgrav return 1; 3837b5038d7SDag-Erling Smørgrav } 3847b5038d7SDag-Erling Smørgrav 3857b5038d7SDag-Erling Smørgrav if (!fd) { 3867b5038d7SDag-Erling Smørgrav if ((rand_f = fopen("/dev/urandom", "r")) == NULL) { 3877b5038d7SDag-Erling Smørgrav /* no readable /dev/urandom, try /dev/random */ 3887b5038d7SDag-Erling Smørgrav if ((rand_f = fopen("/dev/random", "r")) == NULL) { 3897b5038d7SDag-Erling Smørgrav /* no readable /dev/random either, and no entropy 3907b5038d7SDag-Erling Smørgrav source given. we'll have to improvise */ 3917b5038d7SDag-Erling Smørgrav for (read = 0; read < size; read++) { 3927b5038d7SDag-Erling Smørgrav gettimeofday(&tv, NULL); 3937b5038d7SDag-Erling Smørgrav seed[read] = (uint8_t) (tv.tv_usec % 256); 3947b5038d7SDag-Erling Smørgrav } 3957b5038d7SDag-Erling Smørgrav } else { 3967b5038d7SDag-Erling Smørgrav read = fread(seed, 1, size, rand_f); 3977b5038d7SDag-Erling Smørgrav } 3987b5038d7SDag-Erling Smørgrav } else { 3997b5038d7SDag-Erling Smørgrav read = fread(seed, 1, size, rand_f); 4007b5038d7SDag-Erling Smørgrav } 4017b5038d7SDag-Erling Smørgrav } else { 4027b5038d7SDag-Erling Smørgrav rand_f = fd; 4037b5038d7SDag-Erling Smørgrav read = fread(seed, 1, size, rand_f); 4047b5038d7SDag-Erling Smørgrav } 4057b5038d7SDag-Erling Smørgrav 4067b5038d7SDag-Erling Smørgrav if (read < size) { 4077b5038d7SDag-Erling Smørgrav LDNS_FREE(seed); 408*2787e39aSDag-Erling Smørgrav if (!fd) fclose(rand_f); 4097b5038d7SDag-Erling Smørgrav return 1; 4107b5038d7SDag-Erling Smørgrav } else { 4117b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL 4127b5038d7SDag-Erling Smørgrav /* Seed the OpenSSL prng (most systems have it seeded 4137b5038d7SDag-Erling Smørgrav automatically, in that case this call just adds entropy */ 4147b5038d7SDag-Erling Smørgrav RAND_seed(seed, (int) size); 4157b5038d7SDag-Erling Smørgrav #else 4167b5038d7SDag-Erling Smørgrav /* Seed the standard prng, only uses the first 4177b5038d7SDag-Erling Smørgrav * unsigned sizeof(unsiged int) bytes found in the entropy pool 4187b5038d7SDag-Erling Smørgrav */ 4197b5038d7SDag-Erling Smørgrav memcpy(&seed_i, seed, sizeof(seed_i)); 4207b5038d7SDag-Erling Smørgrav srandom(seed_i); 4217b5038d7SDag-Erling Smørgrav #endif 4227b5038d7SDag-Erling Smørgrav LDNS_FREE(seed); 4237b5038d7SDag-Erling Smørgrav } 4247b5038d7SDag-Erling Smørgrav 4257b5038d7SDag-Erling Smørgrav if (!fd) { 4267b5038d7SDag-Erling Smørgrav if (rand_f) fclose(rand_f); 4277b5038d7SDag-Erling Smørgrav } 4287b5038d7SDag-Erling Smørgrav 4297b5038d7SDag-Erling Smørgrav return 0; 4307b5038d7SDag-Erling Smørgrav } 4317b5038d7SDag-Erling Smørgrav 4327b5038d7SDag-Erling Smørgrav /** 4337b5038d7SDag-Erling Smørgrav * Get random number. 4347b5038d7SDag-Erling Smørgrav * 4357b5038d7SDag-Erling Smørgrav */ 4367b5038d7SDag-Erling Smørgrav uint16_t 4377b5038d7SDag-Erling Smørgrav ldns_get_random(void) 4387b5038d7SDag-Erling Smørgrav { 4397b5038d7SDag-Erling Smørgrav uint16_t rid = 0; 4407b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL 4417b5038d7SDag-Erling Smørgrav if (RAND_bytes((unsigned char*)&rid, 2) != 1) { 4427b5038d7SDag-Erling Smørgrav rid = (uint16_t) random(); 4437b5038d7SDag-Erling Smørgrav } 4447b5038d7SDag-Erling Smørgrav #else 4457b5038d7SDag-Erling Smørgrav rid = (uint16_t) random(); 4467b5038d7SDag-Erling Smørgrav #endif 4477b5038d7SDag-Erling Smørgrav return rid; 4487b5038d7SDag-Erling Smørgrav } 4497b5038d7SDag-Erling Smørgrav 4507b5038d7SDag-Erling Smørgrav /* 4517b5038d7SDag-Erling Smørgrav * BubbleBabble code taken from OpenSSH 4527b5038d7SDag-Erling Smørgrav * Copyright (c) 2001 Carsten Raskgaard. All rights reserved. 4537b5038d7SDag-Erling Smørgrav */ 4547b5038d7SDag-Erling Smørgrav char * 4557b5038d7SDag-Erling Smørgrav ldns_bubblebabble(uint8_t *data, size_t len) 4567b5038d7SDag-Erling Smørgrav { 4577b5038d7SDag-Erling Smørgrav char vowels[] = { 'a', 'e', 'i', 'o', 'u', 'y' }; 4587b5038d7SDag-Erling Smørgrav char consonants[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm', 4597b5038d7SDag-Erling Smørgrav 'n', 'p', 'r', 's', 't', 'v', 'z', 'x' }; 4607b5038d7SDag-Erling Smørgrav size_t i, j = 0, rounds, seed = 1; 4617b5038d7SDag-Erling Smørgrav char *retval; 4627b5038d7SDag-Erling Smørgrav 4637b5038d7SDag-Erling Smørgrav rounds = (len / 2) + 1; 4647b5038d7SDag-Erling Smørgrav retval = LDNS_XMALLOC(char, rounds * 6); 4657b5038d7SDag-Erling Smørgrav if(!retval) return NULL; 4667b5038d7SDag-Erling Smørgrav retval[j++] = 'x'; 4677b5038d7SDag-Erling Smørgrav for (i = 0; i < rounds; i++) { 4687b5038d7SDag-Erling Smørgrav size_t idx0, idx1, idx2, idx3, idx4; 4697b5038d7SDag-Erling Smørgrav if ((i + 1 < rounds) || (len % 2 != 0)) { 4707b5038d7SDag-Erling Smørgrav idx0 = (((((size_t)(data[2 * i])) >> 6) & 3) + 4717b5038d7SDag-Erling Smørgrav seed) % 6; 4727b5038d7SDag-Erling Smørgrav idx1 = (((size_t)(data[2 * i])) >> 2) & 15; 4737b5038d7SDag-Erling Smørgrav idx2 = ((((size_t)(data[2 * i])) & 3) + 4747b5038d7SDag-Erling Smørgrav (seed / 6)) % 6; 4757b5038d7SDag-Erling Smørgrav retval[j++] = vowels[idx0]; 4767b5038d7SDag-Erling Smørgrav retval[j++] = consonants[idx1]; 4777b5038d7SDag-Erling Smørgrav retval[j++] = vowels[idx2]; 4787b5038d7SDag-Erling Smørgrav if ((i + 1) < rounds) { 4797b5038d7SDag-Erling Smørgrav idx3 = (((size_t)(data[(2 * i) + 1])) >> 4) & 15; 4807b5038d7SDag-Erling Smørgrav idx4 = (((size_t)(data[(2 * i) + 1]))) & 15; 4817b5038d7SDag-Erling Smørgrav retval[j++] = consonants[idx3]; 4827b5038d7SDag-Erling Smørgrav retval[j++] = '-'; 4837b5038d7SDag-Erling Smørgrav retval[j++] = consonants[idx4]; 4847b5038d7SDag-Erling Smørgrav seed = ((seed * 5) + 4857b5038d7SDag-Erling Smørgrav ((((size_t)(data[2 * i])) * 7) + 4867b5038d7SDag-Erling Smørgrav ((size_t)(data[(2 * i) + 1])))) % 36; 4877b5038d7SDag-Erling Smørgrav } 4887b5038d7SDag-Erling Smørgrav } else { 4897b5038d7SDag-Erling Smørgrav idx0 = seed % 6; 4907b5038d7SDag-Erling Smørgrav idx1 = 16; 4917b5038d7SDag-Erling Smørgrav idx2 = seed / 6; 4927b5038d7SDag-Erling Smørgrav retval[j++] = vowels[idx0]; 4937b5038d7SDag-Erling Smørgrav retval[j++] = consonants[idx1]; 4947b5038d7SDag-Erling Smørgrav retval[j++] = vowels[idx2]; 4957b5038d7SDag-Erling Smørgrav } 4967b5038d7SDag-Erling Smørgrav } 4977b5038d7SDag-Erling Smørgrav retval[j++] = 'x'; 4987b5038d7SDag-Erling Smørgrav retval[j++] = '\0'; 4997b5038d7SDag-Erling Smørgrav return retval; 5007b5038d7SDag-Erling Smørgrav } 501