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