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 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 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 void xprintf_hex(uint8_t *data, size_t len) 54 { 55 size_t i; 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); 59 } 60 printf("%02x ", (unsigned int) data[i]); 61 } 62 printf("\n"); 63 } 64 65 ldns_lookup_table * 66 ldns_lookup_by_name(ldns_lookup_table *table, const char *name) 67 { 68 while (table->name != NULL) { 69 if (strcasecmp(name, table->name) == 0) 70 return table; 71 table++; 72 } 73 return NULL; 74 } 75 76 ldns_lookup_table * 77 ldns_lookup_by_id(ldns_lookup_table *table, int id) 78 { 79 while (table->name != NULL) { 80 if (table->id == id) 81 return table; 82 table++; 83 } 84 return NULL; 85 } 86 87 int 88 ldns_get_bit(uint8_t bits[], size_t index) 89 { 90 /* 91 * The bits are counted from left to right, so bit #0 is the 92 * left most bit. 93 */ 94 return (int) (bits[index / 8] & (1 << (7 - index % 8))); 95 } 96 97 int 98 ldns_get_bit_r(uint8_t bits[], size_t index) 99 { 100 /* 101 * The bits are counted from right to left, so bit #0 is the 102 * right most bit. 103 */ 104 return (int) bits[index / 8] & (1 << (index % 8)); 105 } 106 107 void 108 ldns_set_bit(uint8_t *byte, int bit_nr, bool value) 109 { 110 /* 111 * The bits are counted from right to left, so bit #0 is the 112 * right most bit. 113 */ 114 if (bit_nr >= 0 && bit_nr < 8) { 115 if (value) { 116 *byte = *byte | (0x01 << bit_nr); 117 } else { 118 *byte = *byte & ~(0x01 << bit_nr); 119 } 120 } 121 } 122 123 int 124 ldns_hexdigit_to_int(char ch) 125 { 126 switch (ch) { 127 case '0': return 0; 128 case '1': return 1; 129 case '2': return 2; 130 case '3': return 3; 131 case '4': return 4; 132 case '5': return 5; 133 case '6': return 6; 134 case '7': return 7; 135 case '8': return 8; 136 case '9': return 9; 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; 143 default: 144 return -1; 145 } 146 } 147 148 char 149 ldns_int_to_hexdigit(int i) 150 { 151 switch (i) { 152 case 0: return '0'; 153 case 1: return '1'; 154 case 2: return '2'; 155 case 3: return '3'; 156 case 4: return '4'; 157 case 5: return '5'; 158 case 6: return '6'; 159 case 7: return '7'; 160 case 8: return '8'; 161 case 9: return '9'; 162 case 10: return 'a'; 163 case 11: return 'b'; 164 case 12: return 'c'; 165 case 13: return 'd'; 166 case 14: return 'e'; 167 case 15: return 'f'; 168 default: 169 abort(); 170 } 171 } 172 173 int 174 ldns_hexstring_to_data(uint8_t *data, const char *str) 175 { 176 size_t i; 177 178 if (!str || !data) { 179 return -1; 180 } 181 182 if (strlen(str) % 2 != 0) { 183 return -2; 184 } 185 186 for (i = 0; i < strlen(str) / 2; i++) { 187 data[i] = 188 16 * (uint8_t) ldns_hexdigit_to_int(str[i*2]) + 189 (uint8_t) ldns_hexdigit_to_int(str[i*2 + 1]); 190 } 191 192 return (int) i; 193 } 194 195 const char * 196 ldns_version(void) 197 { 198 return (char*)LDNS_VERSION; 199 } 200 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 204 }; 205 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))) 208 209 static int 210 is_leap_year(int year) 211 { 212 return LDNS_MOD(year, 4) == 0 && (LDNS_MOD(year, 100) != 0 213 || LDNS_MOD(year, 400) == 0); 214 } 215 216 static int 217 leap_days(int y1, int y2) 218 { 219 --y1; 220 --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)); 224 } 225 226 /* 227 * Code adapted from Python 2.4.1 sources (Lib/calendar.py). 228 */ 229 time_t 230 ldns_mktime_from_utc(const struct tm *tm) 231 { 232 int year = 1900 + tm->tm_year; 233 time_t days = 365 * ((time_t) year - 1970) + leap_days(1970, year); 234 time_t hours; 235 time_t minutes; 236 time_t seconds; 237 int i; 238 239 for (i = 0; i < tm->tm_mon; ++i) { 240 days += mdays[i]; 241 } 242 if (tm->tm_mon > 1 && is_leap_year(year)) { 243 ++days; 244 } 245 days += tm->tm_mday - 1; 246 247 hours = days * 24 + tm->tm_hour; 248 minutes = hours * 60 + tm->tm_min; 249 seconds = minutes * 60 + tm->tm_sec; 250 251 return seconds; 252 } 253 254 time_t 255 mktime_from_utc(const struct tm *tm) 256 { 257 return ldns_mktime_from_utc(tm); 258 } 259 260 #if SIZEOF_TIME_T <= 4 261 262 static void 263 ldns_year_and_yday_from_days_since_epoch(int64_t days, struct tm *result) 264 { 265 int year = 1970; 266 int new_year; 267 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); 272 year = new_year; 273 } 274 result->tm_year = year; 275 result->tm_yday = (int) days; 276 } 277 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 281 }; 282 283 static void 284 ldns_mon_and_mday_from_year_and_yday(struct tm *result) 285 { 286 int idays = result->tm_yday; 287 const int *mon_lengths = is_leap_year(result->tm_year) ? 288 leap_year_mdays : mdays; 289 290 result->tm_mon = 0; 291 while (idays >= mon_lengths[result->tm_mon]) { 292 idays -= mon_lengths[result->tm_mon++]; 293 } 294 result->tm_mday = idays + 1; 295 } 296 297 static void 298 ldns_wday_from_year_and_yday(struct tm *result) 299 { 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) 303 + result->tm_yday; 304 result->tm_wday = LDNS_MOD(result->tm_wday, 7); 305 if (result->tm_wday < 0) { 306 result->tm_wday += 7; 307 } 308 } 309 310 static struct tm * 311 ldns_gmtime64_r(int64_t clock, struct tm *result) 312 { 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); 320 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; 325 326 return result; 327 } 328 329 #endif /* SIZEOF_TIME_T <= 4 */ 330 331 static int64_t 332 ldns_serial_arithmitics_time(int32_t time, time_t now) 333 { 334 int32_t offset = time - (int32_t) now; 335 return (int64_t) now + offset; 336 } 337 338 339 struct tm * 340 ldns_serial_arithmitics_gmtime_r(int32_t time, time_t now, struct tm *result) 341 { 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); 345 #else 346 time_t secs_since_epoch = ldns_serial_arithmitics_time(time, now); 347 return gmtime_r(&secs_since_epoch, result); 348 #endif 349 } 350 351 /** 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 355 * or /dev/random 356 * 357 * If you need more entropy, or have no openssl available, this function 358 * MUST be called at the start of the program 359 * 360 * If openssl *is* available, this function just adds more entropy 361 **/ 362 int 363 ldns_init_random(FILE *fd, unsigned int size) 364 { 365 /* if fp is given, seed srandom with data from file 366 otherwise use /dev/urandom */ 367 FILE *rand_f; 368 uint8_t *seed; 369 size_t read = 0; 370 unsigned int seed_i; 371 struct timeval tv; 372 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); 377 } 378 379 seed = LDNS_XMALLOC(uint8_t, size); 380 if(!seed) { 381 return 1; 382 } 383 384 if (!fd) { 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); 393 } 394 } else { 395 read = fread(seed, 1, size, rand_f); 396 } 397 } else { 398 read = fread(seed, 1, size, rand_f); 399 } 400 } else { 401 rand_f = fd; 402 read = fread(seed, 1, size, rand_f); 403 } 404 405 if (read < size) { 406 LDNS_FREE(seed); 407 if (!fd) fclose(rand_f); 408 return 1; 409 } else { 410 #ifdef HAVE_SSL 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); 414 #else 415 /* Seed the standard prng, only uses the first 416 * unsigned sizeof(unsiged int) bytes found in the entropy pool 417 */ 418 memcpy(&seed_i, seed, sizeof(seed_i)); 419 srandom(seed_i); 420 #endif 421 LDNS_FREE(seed); 422 } 423 424 if (!fd) { 425 if (rand_f) fclose(rand_f); 426 } 427 428 return 0; 429 } 430 431 /** 432 * Get random number. 433 * 434 */ 435 uint16_t 436 ldns_get_random(void) 437 { 438 uint16_t rid = 0; 439 #ifdef HAVE_SSL 440 if (RAND_bytes((unsigned char*)&rid, 2) != 1) { 441 rid = (uint16_t) random(); 442 } 443 #else 444 rid = (uint16_t) random(); 445 #endif 446 return rid; 447 } 448 449 /* 450 * BubbleBabble code taken from OpenSSH 451 * Copyright (c) 2001 Carsten Raskgaard. All rights reserved. 452 */ 453 char * 454 ldns_bubblebabble(uint8_t *data, size_t len) 455 { 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; 460 char *retval; 461 462 rounds = (len / 2) + 1; 463 retval = LDNS_XMALLOC(char, rounds * 6); 464 if(!retval) return NULL; 465 retval[j++] = 'x'; 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) + 470 seed) % 6; 471 idx1 = (((size_t)(data[2 * i])) >> 2) & 15; 472 idx2 = ((((size_t)(data[2 * i])) & 3) + 473 (seed / 6)) % 6; 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]; 481 retval[j++] = '-'; 482 retval[j++] = consonants[idx4]; 483 seed = ((seed * 5) + 484 ((((size_t)(data[2 * i])) * 7) + 485 ((size_t)(data[(2 * i) + 1])))) % 36; 486 } 487 } else { 488 idx0 = seed % 6; 489 idx1 = 16; 490 idx2 = seed / 6; 491 retval[j++] = vowels[idx0]; 492 retval[j++] = consonants[idx1]; 493 retval[j++] = vowels[idx2]; 494 } 495 } 496 retval[j++] = 'x'; 497 retval[j++] = '\0'; 498 return retval; 499 } 500