1 /* 2 * util.c 3 * 4 * some general memory functions 5 * 6 * a Net::DNS like library for C 7 * 8 * (c) NLnet Labs, 2004-2006 9 * 10 * See the file LICENSE for the license 11 */ 12 13 #include <ldns/config.h> 14 15 #include <ldns/rdata.h> 16 #include <ldns/rr.h> 17 #include <ldns/util.h> 18 #include <strings.h> 19 #include <stdlib.h> 20 #include <stdio.h> 21 #include <sys/time.h> 22 #include <time.h> 23 24 #ifdef HAVE_SSL 25 #include <openssl/rand.h> 26 #endif 27 28 /* put this here tmp. for debugging */ 29 static void 30 xprintf_rdf(ldns_rdf *rd) 31 { 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)); 37 } 38 39 static void 40 xprintf_rr(ldns_rr *rr) 41 { 42 /* assume printable string */ 43 uint16_t count, i; 44 45 count = ldns_rr_rd_count(rr); 46 47 for(i = 0; i < count; i++) { 48 fprintf(stderr, "print rd %u\n", (unsigned int) i); 49 xprintf_rdf(rr->_rdata_fields[i]); 50 } 51 } 52 53 static void 54 xprintf_hex(uint8_t *data, size_t len) 55 { 56 size_t i; 57 for (i = 0; i < len; i++) { 58 if (i > 0 && i % 20 == 0) { 59 printf("\t; %u - %u\n", (unsigned int) i - 19, (unsigned int) i); 60 } 61 printf("%02x ", (unsigned int) data[i]); 62 } 63 printf("\n"); 64 } 65 66 ldns_lookup_table * 67 ldns_lookup_by_name(ldns_lookup_table *table, const char *name) 68 { 69 while (table->name != NULL) { 70 if (strcasecmp(name, table->name) == 0) 71 return table; 72 table++; 73 } 74 return NULL; 75 } 76 77 ldns_lookup_table * 78 ldns_lookup_by_id(ldns_lookup_table *table, int id) 79 { 80 while (table->name != NULL) { 81 if (table->id == id) 82 return table; 83 table++; 84 } 85 return NULL; 86 } 87 88 int 89 ldns_get_bit(uint8_t bits[], size_t index) 90 { 91 /* 92 * The bits are counted from left to right, so bit #0 is the 93 * left most bit. 94 */ 95 return (int) (bits[index / 8] & (1 << (7 - index % 8))); 96 } 97 98 int 99 ldns_get_bit_r(uint8_t bits[], size_t index) 100 { 101 /* 102 * The bits are counted from right to left, so bit #0 is the 103 * right most bit. 104 */ 105 return (int) bits[index / 8] & (1 << (index % 8)); 106 } 107 108 void 109 ldns_set_bit(uint8_t *byte, int bit_nr, bool value) 110 { 111 /* 112 * The bits are counted from right to left, so bit #0 is the 113 * right most bit. 114 */ 115 if (bit_nr >= 0 && bit_nr < 8) { 116 if (value) { 117 *byte = *byte | (0x01 << bit_nr); 118 } else { 119 *byte = *byte & ~(0x01 << bit_nr); 120 } 121 } 122 } 123 124 int 125 ldns_hexdigit_to_int(char ch) 126 { 127 switch (ch) { 128 case '0': return 0; 129 case '1': return 1; 130 case '2': return 2; 131 case '3': return 3; 132 case '4': return 4; 133 case '5': return 5; 134 case '6': return 6; 135 case '7': return 7; 136 case '8': return 8; 137 case '9': return 9; 138 case 'a': case 'A': return 10; 139 case 'b': case 'B': return 11; 140 case 'c': case 'C': return 12; 141 case 'd': case 'D': return 13; 142 case 'e': case 'E': return 14; 143 case 'f': case 'F': return 15; 144 default: 145 return -1; 146 } 147 } 148 149 char 150 ldns_int_to_hexdigit(int i) 151 { 152 switch (i) { 153 case 0: return '0'; 154 case 1: return '1'; 155 case 2: return '2'; 156 case 3: return '3'; 157 case 4: return '4'; 158 case 5: return '5'; 159 case 6: return '6'; 160 case 7: return '7'; 161 case 8: return '8'; 162 case 9: return '9'; 163 case 10: return 'a'; 164 case 11: return 'b'; 165 case 12: return 'c'; 166 case 13: return 'd'; 167 case 14: return 'e'; 168 case 15: return 'f'; 169 default: 170 abort(); 171 } 172 } 173 174 int 175 ldns_hexstring_to_data(uint8_t *data, const char *str) 176 { 177 size_t i; 178 179 if (!str || !data) { 180 return -1; 181 } 182 183 if (strlen(str) % 2 != 0) { 184 return -2; 185 } 186 187 for (i = 0; i < strlen(str) / 2; i++) { 188 data[i] = 189 16 * (uint8_t) ldns_hexdigit_to_int(str[i*2]) + 190 (uint8_t) ldns_hexdigit_to_int(str[i*2 + 1]); 191 } 192 193 return (int) i; 194 } 195 196 const char * 197 ldns_version(void) 198 { 199 return (char*)LDNS_VERSION; 200 } 201 202 /* Number of days per month (except for February in leap years). */ 203 static const int mdays[] = { 204 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 205 }; 206 207 #define LDNS_MOD(x,y) (((x) % (y) < 0) ? ((x) % (y) + (y)) : ((x) % (y))) 208 #define LDNS_DIV(x,y) (((x) % (y) < 0) ? ((x) / (y) - 1 ) : ((x) / (y))) 209 210 static int 211 is_leap_year(int year) 212 { 213 return LDNS_MOD(year, 4) == 0 && (LDNS_MOD(year, 100) != 0 214 || LDNS_MOD(year, 400) == 0); 215 } 216 217 static int 218 leap_days(int y1, int y2) 219 { 220 --y1; 221 --y2; 222 return (LDNS_DIV(y2, 4) - LDNS_DIV(y1, 4)) - 223 (LDNS_DIV(y2, 100) - LDNS_DIV(y1, 100)) + 224 (LDNS_DIV(y2, 400) - LDNS_DIV(y1, 400)); 225 } 226 227 /* 228 * Code adapted from Python 2.4.1 sources (Lib/calendar.py). 229 */ 230 time_t 231 ldns_mktime_from_utc(const struct tm *tm) 232 { 233 int year = 1900 + tm->tm_year; 234 time_t days = 365 * ((time_t) year - 1970) + leap_days(1970, year); 235 time_t hours; 236 time_t minutes; 237 time_t seconds; 238 int i; 239 240 for (i = 0; i < tm->tm_mon; ++i) { 241 days += mdays[i]; 242 } 243 if (tm->tm_mon > 1 && is_leap_year(year)) { 244 ++days; 245 } 246 days += tm->tm_mday - 1; 247 248 hours = days * 24 + tm->tm_hour; 249 minutes = hours * 60 + tm->tm_min; 250 seconds = minutes * 60 + tm->tm_sec; 251 252 return seconds; 253 } 254 255 time_t 256 mktime_from_utc(const struct tm *tm) 257 { 258 return ldns_mktime_from_utc(tm); 259 } 260 261 #if SIZEOF_TIME_T <= 4 262 263 static void 264 ldns_year_and_yday_from_days_since_epoch(int64_t days, struct tm *result) 265 { 266 int year = 1970; 267 int new_year; 268 269 while (days < 0 || days >= (int64_t) (is_leap_year(year) ? 366 : 365)) { 270 new_year = year + (int) LDNS_DIV(days, 365); 271 days -= (new_year - year) * 365; 272 days -= leap_days(year, new_year); 273 year = new_year; 274 } 275 result->tm_year = year; 276 result->tm_yday = (int) days; 277 } 278 279 /* Number of days per month in a leap year. */ 280 static const int leap_year_mdays[] = { 281 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 282 }; 283 284 static void 285 ldns_mon_and_mday_from_year_and_yday(struct tm *result) 286 { 287 int idays = result->tm_yday; 288 const int *mon_lengths = is_leap_year(result->tm_year) ? 289 leap_year_mdays : mdays; 290 291 result->tm_mon = 0; 292 while (idays >= mon_lengths[result->tm_mon]) { 293 idays -= mon_lengths[result->tm_mon++]; 294 } 295 result->tm_mday = idays + 1; 296 } 297 298 static void 299 ldns_wday_from_year_and_yday(struct tm *result) 300 { 301 result->tm_wday = 4 /* 1-1-1970 was a thursday */ 302 + LDNS_MOD((result->tm_year - 1970), 7) * LDNS_MOD(365, 7) 303 + leap_days(1970, result->tm_year) 304 + result->tm_yday; 305 result->tm_wday = LDNS_MOD(result->tm_wday, 7); 306 if (result->tm_wday < 0) { 307 result->tm_wday += 7; 308 } 309 } 310 311 static struct tm * 312 ldns_gmtime64_r(int64_t clock, struct tm *result) 313 { 314 result->tm_isdst = 0; 315 result->tm_sec = (int) LDNS_MOD(clock, 60); 316 clock = LDNS_DIV(clock, 60); 317 result->tm_min = (int) LDNS_MOD(clock, 60); 318 clock = LDNS_DIV(clock, 60); 319 result->tm_hour = (int) LDNS_MOD(clock, 24); 320 clock = LDNS_DIV(clock, 24); 321 322 ldns_year_and_yday_from_days_since_epoch(clock, result); 323 ldns_mon_and_mday_from_year_and_yday(result); 324 ldns_wday_from_year_and_yday(result); 325 result->tm_year -= 1900; 326 327 return result; 328 } 329 330 #endif /* SIZEOF_TIME_T <= 4 */ 331 332 static int64_t 333 ldns_serial_arithmitics_time(int32_t time, time_t now) 334 { 335 int32_t offset = time - (int32_t) now; 336 return (int64_t) now + offset; 337 } 338 339 340 struct tm * 341 ldns_serial_arithmitics_gmtime_r(int32_t time, time_t now, struct tm *result) 342 { 343 #if SIZEOF_TIME_T <= 4 344 int64_t secs_since_epoch = ldns_serial_arithmitics_time(time, now); 345 return ldns_gmtime64_r(secs_since_epoch, result); 346 #else 347 time_t secs_since_epoch = ldns_serial_arithmitics_time(time, now); 348 return gmtime_r(&secs_since_epoch, result); 349 #endif 350 } 351 352 /** 353 * Init the random source 354 * applications should call this if they need entropy data within ldns 355 * If openSSL is available, it is automatically seeded from /dev/urandom 356 * or /dev/random 357 * 358 * If you need more entropy, or have no openssl available, this function 359 * MUST be called at the start of the program 360 * 361 * If openssl *is* available, this function just adds more entropy 362 **/ 363 int 364 ldns_init_random(FILE *fd, unsigned int size) 365 { 366 /* if fp is given, seed srandom with data from file 367 otherwise use /dev/urandom */ 368 FILE *rand_f; 369 uint8_t *seed; 370 size_t read = 0; 371 unsigned int seed_i; 372 struct timeval tv; 373 374 /* we'll need at least sizeof(unsigned int) bytes for the 375 standard prng seed */ 376 if (size < (unsigned int) sizeof(seed_i)){ 377 size = (unsigned int) sizeof(seed_i); 378 } 379 380 seed = LDNS_XMALLOC(uint8_t, size); 381 if(!seed) { 382 return 1; 383 } 384 385 if (!fd) { 386 if ((rand_f = fopen("/dev/urandom", "r")) == NULL) { 387 /* no readable /dev/urandom, try /dev/random */ 388 if ((rand_f = fopen("/dev/random", "r")) == NULL) { 389 /* no readable /dev/random either, and no entropy 390 source given. we'll have to improvise */ 391 for (read = 0; read < size; read++) { 392 gettimeofday(&tv, NULL); 393 seed[read] = (uint8_t) (tv.tv_usec % 256); 394 } 395 } else { 396 read = fread(seed, 1, size, rand_f); 397 } 398 } else { 399 read = fread(seed, 1, size, rand_f); 400 } 401 } else { 402 rand_f = fd; 403 read = fread(seed, 1, size, rand_f); 404 } 405 406 if (read < size) { 407 LDNS_FREE(seed); 408 if (!fd) fclose(rand_f); 409 return 1; 410 } else { 411 #ifdef HAVE_SSL 412 /* Seed the OpenSSL prng (most systems have it seeded 413 automatically, in that case this call just adds entropy */ 414 RAND_seed(seed, (int) size); 415 #else 416 /* Seed the standard prng, only uses the first 417 * unsigned sizeof(unsiged int) bytes found in the entropy pool 418 */ 419 memcpy(&seed_i, seed, sizeof(seed_i)); 420 srandom(seed_i); 421 #endif 422 LDNS_FREE(seed); 423 } 424 425 if (!fd) { 426 if (rand_f) fclose(rand_f); 427 } 428 429 return 0; 430 } 431 432 /** 433 * Get random number. 434 * 435 */ 436 uint16_t 437 ldns_get_random(void) 438 { 439 uint16_t rid = 0; 440 #ifdef HAVE_SSL 441 if (RAND_bytes((unsigned char*)&rid, 2) != 1) { 442 rid = (uint16_t) random(); 443 } 444 #else 445 rid = (uint16_t) random(); 446 #endif 447 return rid; 448 } 449 450 /* 451 * BubbleBabble code taken from OpenSSH 452 * Copyright (c) 2001 Carsten Raskgaard. All rights reserved. 453 */ 454 char * 455 ldns_bubblebabble(uint8_t *data, size_t len) 456 { 457 char vowels[] = { 'a', 'e', 'i', 'o', 'u', 'y' }; 458 char consonants[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm', 459 'n', 'p', 'r', 's', 't', 'v', 'z', 'x' }; 460 size_t i, j = 0, rounds, seed = 1; 461 char *retval; 462 463 rounds = (len / 2) + 1; 464 retval = LDNS_XMALLOC(char, rounds * 6); 465 if(!retval) return NULL; 466 retval[j++] = 'x'; 467 for (i = 0; i < rounds; i++) { 468 size_t idx0, idx1, idx2, idx3, idx4; 469 if ((i + 1 < rounds) || (len % 2 != 0)) { 470 idx0 = (((((size_t)(data[2 * i])) >> 6) & 3) + 471 seed) % 6; 472 idx1 = (((size_t)(data[2 * i])) >> 2) & 15; 473 idx2 = ((((size_t)(data[2 * i])) & 3) + 474 (seed / 6)) % 6; 475 retval[j++] = vowels[idx0]; 476 retval[j++] = consonants[idx1]; 477 retval[j++] = vowels[idx2]; 478 if ((i + 1) < rounds) { 479 idx3 = (((size_t)(data[(2 * i) + 1])) >> 4) & 15; 480 idx4 = (((size_t)(data[(2 * i) + 1]))) & 15; 481 retval[j++] = consonants[idx3]; 482 retval[j++] = '-'; 483 retval[j++] = consonants[idx4]; 484 seed = ((seed * 5) + 485 ((((size_t)(data[2 * i])) * 7) + 486 ((size_t)(data[(2 * i) + 1])))) % 36; 487 } 488 } else { 489 idx0 = seed % 6; 490 idx1 = 16; 491 idx2 = seed / 6; 492 retval[j++] = vowels[idx0]; 493 retval[j++] = consonants[idx1]; 494 retval[j++] = vowels[idx2]; 495 } 496 } 497 retval[j++] = 'x'; 498 retval[j++] = '\0'; 499 return retval; 500 } 501