4 * some general memory functions
6 * a Net::DNS like library for C
8 * (c) NLnet Labs, 2004-2006
10 * See the file LICENSE for the license
13 #include <ldns/config.h>
15 #include <ldns/rdata.h>
17 #include <ldns/util.h>
25 #include <openssl/rand.h>
28 /* put this here tmp. for debugging */
30 xprintf_rdf(ldns_rdf
*rd
)
32 /* assume printable string */
33 fprintf(stderr
, "size\t:%u\n", (unsigned int)ldns_rdf_size(rd
));
34 fprintf(stderr
, "type\t:%u\n", (unsigned int)ldns_rdf_get_type(rd
));
35 fprintf(stderr
, "data\t:[%.*s]\n", (int)ldns_rdf_size(rd
),
36 (char*)ldns_rdf_data(rd
));
40 xprintf_rr(ldns_rr
*rr
)
42 /* assume printable string */
45 count
= ldns_rr_rd_count(rr
);
47 for(i
= 0; i
< count
; i
++) {
48 fprintf(stderr
, "print rd %u\n", (unsigned int) i
);
49 xprintf_rdf(rr
->_rdata_fields
[i
]);
53 void xprintf_hex(uint8_t *data
, size_t len
)
56 for (i
= 0; i
< len
; i
++) {
57 if (i
> 0 && i
% 20 == 0) {
58 printf("\t; %u - %u\n", (unsigned int) i
- 19, (unsigned int) i
);
60 printf("%02x ", (unsigned int) data
[i
]);
66 ldns_lookup_by_name(ldns_lookup_table
*table
, const char *name
)
68 while (table
->name
!= NULL
) {
69 if (strcasecmp(name
, table
->name
) == 0)
77 ldns_lookup_by_id(ldns_lookup_table
*table
, int id
)
79 while (table
->name
!= NULL
) {
88 ldns_get_bit(uint8_t bits
[], size_t index
)
91 * The bits are counted from left to right, so bit #0 is the
94 return (int) (bits
[index
/ 8] & (1 << (7 - index
% 8)));
98 ldns_get_bit_r(uint8_t bits
[], size_t index
)
101 * The bits are counted from right to left, so bit #0 is the
104 return (int) bits
[index
/ 8] & (1 << (index
% 8));
108 ldns_set_bit(uint8_t *byte
, int bit_nr
, bool value
)
111 * The bits are counted from right to left, so bit #0 is the
114 if (bit_nr
>= 0 && bit_nr
< 8) {
116 *byte
= *byte
| (0x01 << bit_nr
);
118 *byte
= *byte
& ~(0x01 << bit_nr
);
124 ldns_hexdigit_to_int(char ch
)
137 case 'a': case 'A': return 10;
138 case 'b': case 'B': return 11;
139 case 'c': case 'C': return 12;
140 case 'd': case 'D': return 13;
141 case 'e': case 'E': return 14;
142 case 'f': case 'F': return 15;
149 ldns_int_to_hexdigit(int i
)
174 ldns_hexstring_to_data(uint8_t *data
, const char *str
)
182 if (strlen(str
) % 2 != 0) {
186 for (i
= 0; i
< strlen(str
) / 2; i
++) {
188 16 * (uint8_t) ldns_hexdigit_to_int(str
[i
*2]) +
189 (uint8_t) ldns_hexdigit_to_int(str
[i
*2 + 1]);
198 return (char*)LDNS_VERSION
;
201 /* Number of days per month (except for February in leap years). */
202 static const int mdays
[] = {
203 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
206 #define LDNS_MOD(x,y) (((x) % (y) < 0) ? ((x) % (y) + (y)) : ((x) % (y)))
207 #define LDNS_DIV(x,y) (((x) % (y) < 0) ? ((x) / (y) - 1 ) : ((x) / (y)))
210 is_leap_year(int year
)
212 return LDNS_MOD(year
, 4) == 0 && (LDNS_MOD(year
, 100) != 0
213 || LDNS_MOD(year
, 400) == 0);
217 leap_days(int y1
, int y2
)
221 return (LDNS_DIV(y2
, 4) - LDNS_DIV(y1
, 4)) -
222 (LDNS_DIV(y2
, 100) - LDNS_DIV(y1
, 100)) +
223 (LDNS_DIV(y2
, 400) - LDNS_DIV(y1
, 400));
227 * Code adapted from Python 2.4.1 sources (Lib/calendar.py).
230 ldns_mktime_from_utc(const struct tm
*tm
)
232 int year
= 1900 + tm
->tm_year
;
233 time_t days
= 365 * ((time_t) year
- 1970) + leap_days(1970, year
);
239 for (i
= 0; i
< tm
->tm_mon
; ++i
) {
242 if (tm
->tm_mon
> 1 && is_leap_year(year
)) {
245 days
+= tm
->tm_mday
- 1;
247 hours
= days
* 24 + tm
->tm_hour
;
248 minutes
= hours
* 60 + tm
->tm_min
;
249 seconds
= minutes
* 60 + tm
->tm_sec
;
255 mktime_from_utc(const struct tm
*tm
)
257 return ldns_mktime_from_utc(tm
);
260 #if SIZEOF_TIME_T <= 4
263 ldns_year_and_yday_from_days_since_epoch(int64_t days
, struct tm
*result
)
268 while (days
< 0 || days
>= (int64_t) (is_leap_year(year
) ? 366 : 365)) {
269 new_year
= year
+ (int) LDNS_DIV(days
, 365);
270 days
-= (new_year
- year
) * 365;
271 days
-= leap_days(year
, new_year
);
274 result
->tm_year
= year
;
275 result
->tm_yday
= (int) days
;
278 /* Number of days per month in a leap year. */
279 static const int leap_year_mdays
[] = {
280 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
284 ldns_mon_and_mday_from_year_and_yday(struct tm
*result
)
286 int idays
= result
->tm_yday
;
287 const int *mon_lengths
= is_leap_year(result
->tm_year
) ?
288 leap_year_mdays
: mdays
;
291 while (idays
>= mon_lengths
[result
->tm_mon
]) {
292 idays
-= mon_lengths
[result
->tm_mon
++];
294 result
->tm_mday
= idays
+ 1;
298 ldns_wday_from_year_and_yday(struct tm
*result
)
300 result
->tm_wday
= 4 /* 1-1-1970 was a thursday */
301 + LDNS_MOD((result
->tm_year
- 1970), 7) * LDNS_MOD(365, 7)
302 + leap_days(1970, result
->tm_year
)
304 result
->tm_wday
= LDNS_MOD(result
->tm_wday
, 7);
305 if (result
->tm_wday
< 0) {
306 result
->tm_wday
+= 7;
311 ldns_gmtime64_r(int64_t clock
, struct tm
*result
)
313 result
->tm_isdst
= 0;
314 result
->tm_sec
= (int) LDNS_MOD(clock
, 60);
315 clock
= LDNS_DIV(clock
, 60);
316 result
->tm_min
= (int) LDNS_MOD(clock
, 60);
317 clock
= LDNS_DIV(clock
, 60);
318 result
->tm_hour
= (int) LDNS_MOD(clock
, 24);
319 clock
= LDNS_DIV(clock
, 24);
321 ldns_year_and_yday_from_days_since_epoch(clock
, result
);
322 ldns_mon_and_mday_from_year_and_yday(result
);
323 ldns_wday_from_year_and_yday(result
);
324 result
->tm_year
-= 1900;
329 #endif /* SIZEOF_TIME_T <= 4 */
332 ldns_serial_arithmitics_time(int32_t time
, time_t now
)
334 int32_t offset
= time
- (int32_t) now
;
335 return (int64_t) now
+ offset
;
340 ldns_serial_arithmitics_gmtime_r(int32_t time
, time_t now
, struct tm
*result
)
342 #if SIZEOF_TIME_T <= 4
343 int64_t secs_since_epoch
= ldns_serial_arithmitics_time(time
, now
);
344 return ldns_gmtime64_r(secs_since_epoch
, result
);
346 time_t secs_since_epoch
= ldns_serial_arithmitics_time(time
, now
);
347 return gmtime_r(&secs_since_epoch
, result
);
352 * Init the random source
353 * applications should call this if they need entropy data within ldns
354 * If openSSL is available, it is automatically seeded from /dev/urandom
357 * If you need more entropy, or have no openssl available, this function
358 * MUST be called at the start of the program
360 * If openssl *is* available, this function just adds more entropy
363 ldns_init_random(FILE *fd
, unsigned int size
)
365 /* if fp is given, seed srandom with data from file
366 otherwise use /dev/urandom */
373 /* we'll need at least sizeof(unsigned int) bytes for the
374 standard prng seed */
375 if (size
< (unsigned int) sizeof(seed_i
)){
376 size
= (unsigned int) sizeof(seed_i
);
379 seed
= LDNS_XMALLOC(uint8_t, size
);
385 if ((rand_f
= fopen("/dev/urandom", "r")) == NULL
) {
386 /* no readable /dev/urandom, try /dev/random */
387 if ((rand_f
= fopen("/dev/random", "r")) == NULL
) {
388 /* no readable /dev/random either, and no entropy
389 source given. we'll have to improvise */
390 for (read
= 0; read
< size
; read
++) {
391 gettimeofday(&tv
, NULL
);
392 seed
[read
] = (uint8_t) (tv
.tv_usec
% 256);
395 read
= fread(seed
, 1, size
, rand_f
);
398 read
= fread(seed
, 1, size
, rand_f
);
402 read
= fread(seed
, 1, size
, rand_f
);
407 if (!fd
) fclose(rand_f
);
411 /* Seed the OpenSSL prng (most systems have it seeded
412 automatically, in that case this call just adds entropy */
413 RAND_seed(seed
, (int) size
);
415 /* Seed the standard prng, only uses the first
416 * unsigned sizeof(unsiged int) bytes found in the entropy pool
418 memcpy(&seed_i
, seed
, sizeof(seed_i
));
425 if (rand_f
) fclose(rand_f
);
436 ldns_get_random(void)
440 if (RAND_bytes((unsigned char*)&rid
, 2) != 1) {
441 rid
= (uint16_t) random();
444 rid
= (uint16_t) random();
450 * BubbleBabble code taken from OpenSSH
451 * Copyright (c) 2001 Carsten Raskgaard. All rights reserved.
454 ldns_bubblebabble(uint8_t *data
, size_t len
)
456 char vowels
[] = { 'a', 'e', 'i', 'o', 'u', 'y' };
457 char consonants
[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm',
458 'n', 'p', 'r', 's', 't', 'v', 'z', 'x' };
459 size_t i
, j
= 0, rounds
, seed
= 1;
462 rounds
= (len
/ 2) + 1;
463 retval
= LDNS_XMALLOC(char, rounds
* 6);
464 if(!retval
) return NULL
;
466 for (i
= 0; i
< rounds
; i
++) {
467 size_t idx0
, idx1
, idx2
, idx3
, idx4
;
468 if ((i
+ 1 < rounds
) || (len
% 2 != 0)) {
469 idx0
= (((((size_t)(data
[2 * i
])) >> 6) & 3) +
471 idx1
= (((size_t)(data
[2 * i
])) >> 2) & 15;
472 idx2
= ((((size_t)(data
[2 * i
])) & 3) +
474 retval
[j
++] = vowels
[idx0
];
475 retval
[j
++] = consonants
[idx1
];
476 retval
[j
++] = vowels
[idx2
];
477 if ((i
+ 1) < rounds
) {
478 idx3
= (((size_t)(data
[(2 * i
) + 1])) >> 4) & 15;
479 idx4
= (((size_t)(data
[(2 * i
) + 1]))) & 15;
480 retval
[j
++] = consonants
[idx3
];
482 retval
[j
++] = consonants
[idx4
];
484 ((((size_t)(data
[2 * i
])) * 7) +
485 ((size_t)(data
[(2 * i
) + 1])))) % 36;
491 retval
[j
++] = vowels
[idx0
];
492 retval
[j
++] = consonants
[idx1
];
493 retval
[j
++] = vowels
[idx2
];