spf_dns_cache.c

Go to the documentation of this file.
00001 /*
00002  * This program is free software; you can redistribute it and/or modify
00003  * it under the terms of either:
00004  *
00005  *   a) The GNU Lesser General Public License as published by the Free
00006  *      Software Foundation; either version 2.1, or (at your option) any
00007  *      later version,
00008  *
00009  *   OR
00010  *
00011  *   b) The two-clause BSD license.
00012  *
00013  * These licenses can be found with the distribution in the file LICENSES
00014  */
00015 
00016 #include "spf_sys_config.h"
00017 
00018 #ifdef STDC_HEADERS
00019 # include <stdio.h>        /* stdin / stdout */
00020 # include <stdlib.h>       /* malloc / free */
00021 #endif
00022 
00023 
00024 #ifdef HAVE_STRING_H
00025 # include <string.h>       /* strstr / strdup */
00026 #else
00027 # ifdef HAVE_STRINGS_H
00028 #  include <strings.h>       /* strstr / strdup */
00029 # endif
00030 #endif
00031 
00032 #ifdef HAVE_MEMORY_H
00033 #include <memory.h>
00034 #endif
00035 #if TIME_WITH_SYS_TIME
00036 # include <sys/time.h>
00037 # include <time.h>
00038 #else
00039 # if HAVE_SYS_TIME_H
00040 #  include <sys/time.h>
00041 # else
00042 #  include <time.h>
00043 # endif
00044 #endif
00045 
00046 #ifdef HAVE_NETDB_H
00047 # include <netdb.h>
00048 #endif
00049 
00050 #ifdef HAVE_PTHREAD_H
00051 # include <pthread.h>
00052 #endif
00053 
00054 #include "spf.h"
00055 #include "spf_dns.h"
00056 #include "spf_internal.h"
00057 #include "spf_dns_internal.h"
00058 #include "spf_dns_cache.h"
00059 
00060 
00082 typedef
00083 struct _SPF_dns_cache_bucket_t {
00084         struct _SPF_dns_cache_bucket_t  *next;
00085         SPF_dns_rr_t                                    *rr;
00086 } SPF_dns_cache_bucket_t;
00087 
00088 typedef struct
00089 {
00090     SPF_dns_cache_bucket_t      **cache;
00091     int                                           cache_size;
00092     pthread_mutex_t                       cache_lock;
00093 
00094     int                         hash_mask;
00095     int                         max_hash_len;
00096 
00097 #if 0
00098     int                         hit;
00099     int                         miss;
00100 #endif
00101 
00102     time_t                      min_ttl;
00103     time_t                      err_ttl;
00104     time_t                      txt_ttl;
00105     time_t                      rdns_ttl;
00106 
00107     int                         conserve_cache;
00108 
00109     
00110 } SPF_dns_cache_config_t;
00111 
00112 
00113 static inline SPF_dns_cache_config_t *SPF_voidp2spfhook( void *hook )
00114     { return (SPF_dns_cache_config_t *)hook; }
00115 static inline void *SPF_spfhook2voidp( SPF_dns_cache_config_t *spfhook )
00116     { return (void *)spfhook; }
00117 
00118 
00119 /*
00120 ** calculate CRC-32 stuff.
00121 */
00122 
00123 /*
00124  *  COPYRIGHT (C) 1986 Gary S. Brown.  You may use this program, or
00125  *  code or tables extracted from it, as desired without restriction.
00126  *
00127  *  First, the polynomial itself and its table of feedback terms.  The
00128  *  polynomial is
00129  *  X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0
00130  *
00131  *  Note that we take it "backwards" and put the highest-order term in
00132  *  the lowest-order bit.  The X^32 term is "implied"; the LSB is the
00133  *  X^31 term, etc.  The X^0 term (usually shown as "+1") results in
00134  *  the MSB being 1
00135  *
00136  *  Note that the usual hardware shift register implementation, which
00137  *  is what we're using (we're merely optimizing it by doing eight-bit
00138  *  chunks at a time) shifts bits into the lowest-order term.  In our
00139  *  implementation, that means shifting towards the right.  Why do we
00140  *  do it this way?  Because the calculated CRC must be transmitted in
00141  *  order from highest-order term to lowest-order term.  UARTs transmit
00142  *  characters in order from LSB to MSB.  By storing the CRC this way
00143  *  we hand it to the UART in the order low-byte to high-byte; the UART
00144  *  sends each low-bit to hight-bit; and the result is transmission bit
00145  *  by bit from highest- to lowest-order term without requiring any bit
00146  *  shuffling on our part.  Reception works similarly
00147  *
00148  *  The feedback terms table consists of 256, 32-bit entries.  Notes
00149  *
00150  *      The table can be generated at runtime if desired; code to do so
00151  *      is shown later.  It might not be obvious, but the feedback
00152  *      terms simply represent the results of eight shift/xor opera
00153  *      tions for all combinations of data and CRC register values
00154  *
00155  *      The values must be right-shifted by eight bits by the "updcrc
00156  *      logic; the shift must be unsigned (bring in zeroes).  On some
00157  *      hardware you could probably optimize the shift in assembler by
00158  *      using byte-swap instructions
00159  *      polynomial $edb88320
00160  */
00161 
00162 const unsigned int crc_32_tab[256] = {
00163         0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
00164         0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
00165         0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
00166         0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
00167         0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
00168         0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
00169         0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
00170         0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
00171         0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
00172         0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
00173         0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
00174         0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
00175         0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
00176         0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
00177         0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
00178         0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
00179         0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
00180         0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
00181         0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
00182         0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
00183         0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
00184         0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
00185         0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
00186         0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
00187         0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
00188         0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
00189         0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
00190         0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
00191         0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
00192         0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
00193         0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
00194         0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
00195         0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
00196         0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
00197         0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
00198         0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
00199         0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
00200         0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
00201         0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
00202         0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
00203         0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
00204         0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
00205         0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
00206         0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
00207         0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
00208         0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
00209         0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
00210         0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
00211         0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
00212         0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
00213         0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
00214         0x2d02ef8dL
00215 };
00216 
00217 static inline int
00218 crc32str(unsigned int accum, const char *str, int max_hash_len)
00219 {
00220     for( ; *str != '\0' && max_hash_len > 0; str++ ) {
00221                 if ( *str == '.' )
00222                         continue;
00223 
00224                 accum = crc_32_tab[ (unsigned char)accum ^ (unsigned char)*str ]
00225                         ^ (unsigned char)(accum >> 8);
00226 
00227                 max_hash_len--;
00228         }
00229 
00230 
00231         return accum;
00232 }
00233 
00234 // #define hash(h,s,a) (crc32str(a,s,h->max_hash_len) & (h->hash_mask))
00235 #define hash(h,s,a) crc32str(a,s,h->max_hash_len)
00236 
00237 /* This must be called with the lock held. */
00238 static SPF_dns_cache_bucket_t *
00239 SPF_dns_cache_bucket_find(SPF_dns_cache_config_t *spfhook,
00240                                 const char *domain, ns_type rr_type, int idx)
00241 {
00242         SPF_dns_cache_bucket_t  *bucket;
00243         SPF_dns_cache_bucket_t  *prev;
00244         SPF_dns_rr_t                    *rr;
00245         time_t                                   now;
00246 
00247     bucket = spfhook->cache[idx];
00248         prev = NULL;
00249         time(&now);
00250 
00251         while (bucket != NULL) {
00252                 rr = bucket->rr;
00253 
00254                 if (rr->utc_ttl < now) {
00255                         /* Unlink the bucket. */
00256                         if (prev != NULL)
00257                                 prev->next = bucket->next;
00258                         else
00259                                 spfhook->cache[idx] = bucket->next;
00260                         /* Free the bucket. */
00261                         if (bucket->rr)
00262                                 SPF_dns_rr_free(bucket->rr);
00263                         free(bucket);
00264                         /* Set iterator back one step. */
00265                         bucket = prev;  /* Might be NULL */
00266                 }
00267                 else if (rr->rr_type != rr_type) {
00268                         /* Types differ */
00269                 }
00270                 else if (strcmp(rr->domain, domain) != 0) {
00271                         /* Domains differ */
00272                 }
00273                 else {
00274                         /* Move the bucket to the top of the chain. */
00275                         if (prev != NULL) {
00276                                 prev->next = bucket->next;
00277                                 bucket->next = spfhook->cache[idx];
00278                                 spfhook->cache[idx] = bucket;
00279                         }
00280                         return bucket;
00281                 }
00282 
00283                 prev = bucket;          /* Might be NULL */
00284                 if (bucket == NULL)     /* After an unlink */
00285                         bucket = spfhook->cache[idx];
00286                 else
00287                         bucket = bucket->next;
00288         }
00289 
00290         return NULL;
00291 }
00292 
00293 /* This must be called with the lock held. */
00294 static SPF_errcode_t
00295 SPF_dns_cache_bucket_add(SPF_dns_cache_config_t *spfhook,
00296                                 SPF_dns_rr_t *rr, int idx)
00297 {
00298         SPF_dns_cache_bucket_t  *bucket;
00299 
00300         bucket = (SPF_dns_cache_bucket_t *)
00301                                 malloc(sizeof(SPF_dns_cache_bucket_t));
00302         if (! bucket)
00303                 return SPF_E_NO_MEMORY;
00304         bucket->next = spfhook->cache[idx];
00305         spfhook->cache[idx] = bucket;
00306         bucket->rr = rr;
00307         return SPF_E_SUCCESS;
00308 }
00309 
00310 
00314 static SPF_errcode_t
00315 SPF_dns_cache_rr_fixup(SPF_dns_cache_config_t *spfhook,
00316                                 SPF_dns_rr_t *cached_rr,
00317                                 const char *domain, ns_type rr_type)
00318 {
00319     char                        *p;
00320 
00321     /* make sure the RR has enough data to be useful for caching */
00322     if (cached_rr->rr_type == ns_t_any)
00323                 cached_rr->rr_type = rr_type;
00324 
00325         /* XXX I'm still not sure about this bit. */
00326         if (cached_rr->domain == NULL || cached_rr->domain[0] != '\0') {
00327                 char    *new_domain;
00328                 size_t   new_len = strlen(domain) + 1;
00329 
00330                 if (cached_rr->domain_buf_len < new_len) {
00331                         new_domain = realloc(cached_rr->domain, new_len);
00332                         if (new_domain == NULL)
00333                                 return SPF_E_NO_MEMORY;
00334                         cached_rr->domain = new_domain;
00335                         cached_rr->domain_buf_len = new_len;
00336                 }
00337                 strcpy(cached_rr->domain, domain);
00338         }
00339 
00340     /* set up the ttl values */
00341     if ( cached_rr->ttl < spfhook->min_ttl )
00342                 cached_rr->ttl = spfhook->min_ttl;
00343 
00344     if ( cached_rr->ttl < spfhook->txt_ttl
00345                         && cached_rr->rr_type == ns_t_txt )
00346                 cached_rr->ttl = spfhook->txt_ttl;
00347 
00348     if ( cached_rr->ttl < spfhook->err_ttl
00349                         && cached_rr->herrno != NETDB_SUCCESS )
00350                 cached_rr->ttl = spfhook->err_ttl;
00351 
00352     if ( cached_rr->ttl < spfhook->rdns_ttl ) {
00353                 p = strstr( cached_rr->domain, ".arpa" );
00354                 if ( p && p[ sizeof( ".arpa" )-1 ] == '\0' )
00355                         cached_rr->ttl = spfhook->rdns_ttl;
00356     }
00357 
00358         cached_rr->utc_ttl = cached_rr->ttl + time(NULL);
00359 
00360         return SPF_E_SUCCESS;
00361 }
00362 
00363 
00367 static SPF_dns_rr_t *
00368 SPF_dns_cache_lookup(SPF_dns_server_t *spf_dns_server,
00369                                 const char *domain, ns_type rr_type, int should_cache)
00370 {
00371     SPF_dns_cache_config_t      *spfhook;
00372         SPF_dns_cache_bucket_t  *bucket;
00373         SPF_dns_rr_t                    *cached_rr;
00374         SPF_dns_rr_t                    *rr;
00375     int                                          idx;
00376 
00377         spfhook = SPF_voidp2spfhook(spf_dns_server->hook);
00378 
00379         /* max_hash_len and cache_size are constant, so this be done
00380          * outside the lock. */
00381         idx = hash(spfhook, domain, 0 /* spfhook->hash_mask+rr_type */);
00382         idx &= (spfhook->cache_size - 1);
00383 
00384     pthread_mutex_lock(&(spfhook->cache_lock));
00385 
00386         bucket = SPF_dns_cache_bucket_find(spfhook, domain, rr_type, idx);
00387         if (bucket != NULL) {
00388                 if (bucket->rr != NULL) {
00389                         if (SPF_dns_rr_dup(&rr, bucket->rr) == SPF_E_SUCCESS) {
00390                                 pthread_mutex_unlock(&(spfhook->cache_lock));
00391                                 return rr;
00392                         }
00393                         else if (rr != NULL) {
00394                                 SPF_dns_rr_free(rr);    /* Within the lock. :-( */
00395                         }
00396                 }
00397         }
00398 
00399         /* Make sure we don't hang onto this outside the lock.
00400          * idx is presumably safe. */
00401         bucket = NULL;
00402 
00403         pthread_mutex_unlock(&(spfhook->cache_lock));
00404 
00405     if (!spf_dns_server->layer_below)
00406                 return SPF_dns_rr_new_nxdomain(spf_dns_server, domain);
00407 
00408         rr = SPF_dns_lookup( spf_dns_server->layer_below,
00409                                         domain, rr_type, should_cache );
00410     if (spfhook->conserve_cache && !should_cache)
00411                 return rr;
00412 
00413     pthread_mutex_lock(&(spfhook->cache_lock));
00414 
00415         if (SPF_dns_rr_dup(&cached_rr, rr) == SPF_E_SUCCESS) {
00416                 if (SPF_dns_cache_rr_fixup(spfhook, cached_rr, domain, rr_type) == SPF_E_SUCCESS){
00417                         if (SPF_dns_cache_bucket_add(spfhook, cached_rr, idx) == SPF_E_SUCCESS) {
00418                                 pthread_mutex_unlock(&(spfhook->cache_lock));
00419                                 return rr;
00420                         }
00421                 }
00422         }
00423 
00424     pthread_mutex_unlock(&(spfhook->cache_lock));
00425 
00426         if (cached_rr)
00427                 SPF_dns_rr_free(cached_rr);
00428 
00429         return rr;
00430 
00431 }
00432 
00433 
00434 static void
00435 SPF_dns_cache_free( SPF_dns_server_t *spf_dns_server )
00436 {
00437     SPF_dns_cache_config_t      *spfhook;
00438         SPF_dns_cache_bucket_t  *bucket;
00439         SPF_dns_cache_bucket_t  *prev;
00440     int                                          i;
00441 
00442         SPF_ASSERT_NOTNULL(spf_dns_server);
00443 
00444     spfhook = SPF_voidp2spfhook( spf_dns_server->hook );
00445         if ( spfhook ) {
00446                 pthread_mutex_lock(&(spfhook->cache_lock));
00447         
00448                 if (spfhook->cache) {
00449                         for( i = 0; i < spfhook->cache_size; i++ ) {
00450                                 bucket = spfhook->cache[i];
00451                                 while (bucket != NULL) {
00452                                         prev = bucket;
00453                                         bucket = bucket->next;
00454 
00455                                         /* Free the bucket. */
00456                                         if (prev->rr)
00457                                                 SPF_dns_rr_free(prev->rr);
00458                                         free(prev);
00459                                 }
00460                         }
00461                         free(spfhook->cache);
00462                         spfhook->cache = NULL;
00463                 }
00464 
00465                 pthread_mutex_unlock(&(spfhook->cache_lock));
00466 
00467                 /* 
00468                  * There is a risk that something might grab the mutex
00469                  * here and try to look things up and try to resolve
00470                  * stuff from a mashed cache it might happen but that's
00471                  * what you get for trying to simultaneously free and
00472                  * use a resource destroy will then return EBUSY but
00473                  * it'll probably segfault so there ain't much to be
00474                  * done really.
00475                  */
00476                 pthread_mutex_destroy(&(spfhook->cache_lock));
00477 
00478                 free(spfhook);
00479         }
00480 
00481     free(spf_dns_server);
00482 }
00483 
00484 
00485 
00486 SPF_dns_server_t *
00487 SPF_dns_cache_new(SPF_dns_server_t *layer_below,
00488                                 const char *name, int debug, int cache_bits)
00489 {
00490         SPF_dns_server_t                *spf_dns_server;
00491     SPF_dns_cache_config_t      *spfhook;
00492 
00493         SPF_ASSERT_NOTNULL(layer_below);
00494 
00495     if ( cache_bits < 1 || cache_bits > 16 )
00496                 SPF_error( "cache bits out of range (1..16)." );
00497 
00498 
00499         spf_dns_server = malloc(sizeof(SPF_dns_server_t));
00500     if (spf_dns_server == NULL)
00501                 return NULL;
00502         memset(spf_dns_server, 0, sizeof(SPF_dns_server_t));
00503 
00504     spf_dns_server->hook = malloc(sizeof(SPF_dns_cache_config_t));
00505     if (spf_dns_server->hook == NULL) {
00506                 free(spf_dns_server);
00507                 return NULL;
00508     }
00509         memset(spf_dns_server->hook, 0, sizeof(SPF_dns_cache_config_t));
00510 
00511         if (name == NULL)
00512                 name = "cache";
00513 
00514     spf_dns_server->destroy     = SPF_dns_cache_free;
00515     spf_dns_server->lookup      = SPF_dns_cache_lookup;
00516     spf_dns_server->get_spf     = NULL;
00517     spf_dns_server->get_exp     = NULL;
00518     spf_dns_server->add_cache   = NULL;
00519     spf_dns_server->layer_below = layer_below;
00520     spf_dns_server->name        = name;
00521     spf_dns_server->debug       = debug;
00522 
00523     spfhook = SPF_voidp2spfhook( spf_dns_server->hook );
00524 
00525         spfhook->cache_size = 1 << cache_bits;
00526         spfhook->hash_mask  = spfhook->cache_size - 1;
00527         spfhook->max_hash_len = cache_bits > 4 ? cache_bits * 2 : 8;
00528 
00529     spfhook->cache = calloc(spfhook->cache_size,
00530                                                                         sizeof(*spfhook->cache));
00531 
00532 #if 0
00533     spfhook->hit        = 0;
00534     spfhook->miss       = 0;
00535 #endif
00536 
00537     spfhook->min_ttl    = 30;
00538     spfhook->err_ttl    = 30*60;
00539     spfhook->txt_ttl    = 30*60;
00540     spfhook->rdns_ttl   = 30*60;
00541     spfhook->conserve_cache  = cache_bits < 12;
00542 
00543     if (spfhook->cache == NULL) {
00544                 free(spfhook);
00545                 free(spf_dns_server);
00546                 return NULL;
00547     }
00548 
00549         pthread_mutex_init(&(spfhook->cache_lock),NULL);
00550 
00551     return spf_dns_server;
00552 }
00553 
00554 void
00555 SPF_dns_cache_set_ttl( SPF_dns_server_t *spf_dns_server,
00556                                 time_t min_ttl, time_t err_ttl,
00557                                 time_t txt_ttl, time_t rdns_ttl )
00558 {
00559     SPF_dns_cache_config_t *spfhook;
00560 
00561         SPF_ASSERT_NOTNULL(spf_dns_server);
00562 
00563     spfhook = SPF_voidp2spfhook( spf_dns_server->hook );
00564 
00565     if (spfhook != NULL) {
00566         pthread_mutex_lock(&(spfhook->cache_lock));
00567         spfhook->min_ttl  = min_ttl;
00568         spfhook->err_ttl  = err_ttl;
00569         spfhook->txt_ttl  = txt_ttl;
00570         spfhook->rdns_ttl = rdns_ttl;
00571         pthread_mutex_unlock(&(spfhook->cache_lock));
00572     }
00573 }
00574 
00575 
00576 void
00577 SPF_dns_set_conserve_cache( SPF_dns_server_t *spf_dns_server,
00578                                 int conserve_cache )
00579 {
00580     SPF_dns_cache_config_t *spfhook;
00581 
00582         SPF_ASSERT_NOTNULL(spf_dns_server);
00583 
00584     spfhook = SPF_voidp2spfhook( spf_dns_server->hook );
00585         /* This is a boolean and it doesn't matter if it
00586          * changes suddenly, thus no lock. */
00587     if (spfhook != NULL)
00588         spfhook->conserve_cache = conserve_cache;
00589 }

Generated on Tue Nov 4 13:27:39 2008 for libspf2 by  doxygen 1.5.4