util.c

Go to the documentation of this file.
00001 /*
00002  * util.c
00003  *
00004  * some general memory functions
00005  *
00006  * a Net::DNS like library for C
00007  *
00008  * (c) NLnet Labs, 2004-2006
00009  *
00010  * See the file LICENSE for the license
00011  */
00012 
00013 #include <ldns/config.h>
00014 
00015 #include <ldns/rdata.h>
00016 #include <ldns/rr.h>
00017 #include <ldns/util.h>
00018 #include <strings.h>
00019 #include <stdlib.h>
00020 #include <stdio.h>
00021 #include <sys/time.h>
00022 #include <time.h>
00023 
00024 #ifdef HAVE_SSL
00025 #include <openssl/rand.h>
00026 #endif
00027 
00028 /* put this here tmp. for debugging */
00029 void
00030 xprintf_rdf(ldns_rdf *rd)
00031 {
00032         /* assume printable string */
00033         fprintf(stderr, "size\t:%u\n", (unsigned int)ldns_rdf_size(rd));
00034         fprintf(stderr, "type\t:%u\n", (unsigned int)ldns_rdf_get_type(rd));
00035         fprintf(stderr, "data\t:[%.*s]\n", (int)ldns_rdf_size(rd), 
00036                         (char*)ldns_rdf_data(rd));
00037 }
00038 
00039 void
00040 xprintf_rr(ldns_rr *rr)
00041 {
00042         /* assume printable string */
00043         uint16_t count, i;
00044 
00045         count = ldns_rr_rd_count(rr);
00046 
00047         for(i = 0; i < count; i++) {
00048                 fprintf(stderr, "print rd %u\n", (unsigned int) i);
00049                 xprintf_rdf(rr->_rdata_fields[i]);
00050         }
00051 }
00052 
00053 ldns_lookup_table *
00054 ldns_lookup_by_name(ldns_lookup_table *table, const char *name)
00055 {
00056         while (table->name != NULL) {
00057                 if (strcasecmp(name, table->name) == 0)
00058                         return table;
00059                 table++;
00060         }
00061         return NULL;
00062 }
00063 
00064 ldns_lookup_table *
00065 ldns_lookup_by_id(ldns_lookup_table *table, int id)
00066 {
00067         while (table->name != NULL) {
00068                 if (table->id == id)
00069                         return table;
00070                 table++;
00071         }
00072         return NULL;
00073 }
00074 
00075 int 
00076 ldns_get_bit(uint8_t bits[], size_t index)
00077 {
00078         /*
00079          * The bits are counted from left to right, so bit #0 is the
00080          * left most bit.
00081          */
00082         return (int) (bits[index / 8] & (1 << (7 - index % 8)));
00083 }
00084 
00085 int 
00086 ldns_get_bit_r(uint8_t bits[], size_t index)
00087 {
00088         /*
00089          * The bits are counted from right to left, so bit #0 is the
00090          * right most bit.
00091          */
00092         return (int) bits[index / 8] & (1 << (index % 8));
00093 }
00094 
00095 void
00096 ldns_set_bit(uint8_t *byte, int bit_nr, bool value) 
00097 {
00098         if (bit_nr >= 0 && bit_nr < 8) {
00099                 if (value) {
00100                         *byte = *byte | (0x01 << bit_nr);
00101                 } else {
00102                         *byte = *byte & !(0x01 << bit_nr);
00103                 }
00104         }
00105 }
00106 
00107 int
00108 ldns_hexdigit_to_int(char ch)
00109 {
00110         switch (ch) {
00111         case '0': return 0;
00112         case '1': return 1;
00113         case '2': return 2;
00114         case '3': return 3;
00115         case '4': return 4;
00116         case '5': return 5;
00117         case '6': return 6;
00118         case '7': return 7;
00119         case '8': return 8;
00120         case '9': return 9;
00121         case 'a': case 'A': return 10;
00122         case 'b': case 'B': return 11;
00123         case 'c': case 'C': return 12;
00124         case 'd': case 'D': return 13;
00125         case 'e': case 'E': return 14;
00126         case 'f': case 'F': return 15;
00127         default:
00128                 return -1;
00129         }
00130 }
00131 
00132 char 
00133 ldns_int_to_hexdigit(int i)
00134 {
00135         switch (i) {
00136         case 0: return '0';
00137         case 1: return '1';
00138         case 2: return '2';
00139         case 3: return '3';
00140         case 4: return '4';
00141         case 5: return '5';
00142         case 6: return '6';
00143         case 7: return '7';
00144         case 8: return '8';
00145         case 9: return '9';
00146         case 10: return 'a';
00147         case 11: return 'b';
00148         case 12: return 'c';
00149         case 13: return 'd';
00150         case 14: return 'e';
00151         case 15: return 'f';
00152         default:
00153                 abort();
00154         }
00155 }
00156 
00157 const char *
00158 ldns_version(void)
00159 {
00160         return (char*)LDNS_VERSION;
00161 }
00162 
00163 /* Number of days per month (except for February in leap years). */
00164 static const int mdays[] = {
00165         31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
00166 };
00167 
00168 static int 
00169 is_leap_year(int year)
00170 {
00171         return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
00172 }
00173 
00174 static int
00175 leap_days(int y1, int y2)
00176 {
00177         --y1;
00178         --y2;
00179         return (y2/4 - y1/4) - (y2/100 - y1/100) + (y2/400 - y1/400);
00180 }
00181 
00182 /*
00183  * Code adapted from Python 2.4.1 sources (Lib/calendar.py).
00184  */
00185 time_t
00186 mktime_from_utc(const struct tm *tm)
00187 {
00188         int year = 1900 + tm->tm_year;
00189         time_t days = 365 * ((time_t) year - 1970) + leap_days(1970, year);
00190         time_t hours;
00191         time_t minutes;
00192         time_t seconds;
00193         int i;
00194 
00195         for (i = 0; i < tm->tm_mon; ++i) {
00196                 days += mdays[i];
00197         }
00198         if (tm->tm_mon > 1 && is_leap_year(year)) {
00199                 ++days;
00200         }
00201         days += tm->tm_mday - 1;
00202 
00203         hours = days * 24 + tm->tm_hour;
00204         minutes = hours * 60 + tm->tm_min;
00205         seconds = minutes * 60 + tm->tm_sec;
00206 
00207         return seconds;
00208 }
00209 
00221 int
00222 ldns_init_random(FILE *fd, unsigned int size) 
00223 {
00224         /* if fp is given, seed srandom with data from file
00225            otherwise use /dev/urandom */
00226         FILE *rand_f;
00227         unsigned int *seed;
00228         size_t read = 0;
00229         unsigned int seed_i;
00230         struct timeval tv;
00231         struct timezone tz;
00232 
00233         /* we'll need at least sizeof(unsigned int) bytes for the
00234            standard prng seed */
00235         if (size < sizeof(seed_i)){
00236                 size = sizeof(seed_i);
00237         }
00238         
00239         seed = LDNS_XMALLOC(unsigned int, size);
00240 
00241         if (!fd) {
00242                 if ((rand_f = fopen("/dev/urandom", "r")) == NULL) {
00243                         /* no readable /dev/urandom, try /dev/random */
00244                         if ((rand_f = fopen("/dev/random", "r")) == NULL) {
00245                                 /* no readable /dev/random either, and no entropy
00246                                    source given. we'll have to improvise */
00247                                 for (read = 0; read < size; read++) {
00248                                         gettimeofday(&tv, &tz);
00249                                         seed[read] = (uint8_t) (tv.tv_usec % 256);
00250                                 }
00251                         }
00252                 }
00253         } else {
00254                 rand_f = fd;
00255                 read = fread(seed, 1, size, rand_f);
00256         }
00257         
00258         if (read < size) {
00259                 LDNS_FREE(seed);
00260                 return 1;
00261         } else {
00262 #ifdef HAVE_SSL
00263                 /* Seed the OpenSSL prng (most systems have it seeded
00264                    automatically, in that case this call just adds entropy */
00265                 RAND_seed(seed, size);
00266 #else
00267                 /* Seed the standard prng, only uses the first
00268                  * unsigned sizeof(unsiged int) bytes found in the entropy pool
00269                  */
00270                 memcpy(&seed_i, seed, sizeof(seed_i));
00271                 srandom(seed_i);
00272 #endif
00273                 LDNS_FREE(seed);
00274         }
00275         
00276         if (!fd) {
00277                 fclose(rand_f);
00278         }
00279 
00280         return 0;
00281 }
00282 

Generated on Thu Nov 29 13:39:19 2007 for ldns by  doxygen 1.5.2