libspf2  1.2.11
spf_dns_cache.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or modify
3  * it under the terms of either:
4  *
5  * a) The GNU Lesser General Public License as published by the Free
6  * Software Foundation; either version 2.1, or (at your option) any
7  * later version,
8  *
9  * OR
10  *
11  * b) The two-clause BSD license.
12  *
13  * These licenses can be found with the distribution in the file LICENSES
14  */
15 
16 #include "spf_sys_config.h"
17 
18 #ifdef STDC_HEADERS
19 # include <stdio.h> /* stdin / stdout */
20 # include <stdlib.h> /* malloc / free */
21 #endif
22 
23 
24 #ifdef HAVE_STRING_H
25 # include <string.h> /* strstr / strdup */
26 #else
27 # ifdef HAVE_STRINGS_H
28 # include <strings.h> /* strstr / strdup */
29 # endif
30 #endif
31 
32 #ifdef HAVE_MEMORY_H
33 #include <memory.h>
34 #endif
35 #if TIME_WITH_SYS_TIME
36 # include <sys/time.h>
37 # include <time.h>
38 #else
39 # if HAVE_SYS_TIME_H
40 # include <sys/time.h>
41 # else
42 # include <time.h>
43 # endif
44 #endif
45 
46 #ifdef HAVE_NETDB_H
47 # include <netdb.h>
48 #endif
49 
50 #ifdef HAVE_PTHREAD_H
51 # include <pthread.h>
52 #endif
53 
54 #include "spf.h"
55 #include "spf_dns.h"
56 #include "spf_internal.h"
57 #include "spf_dns_internal.h"
58 #include "spf_dns_cache.h"
59 
60 
82 typedef
83 struct _SPF_dns_cache_bucket_t {
84  struct _SPF_dns_cache_bucket_t *next;
87 
88 typedef struct
89 {
92  pthread_mutex_t cache_lock;
93 
94  int hash_mask;
96 
97 #if 0
98  int hit;
99  int miss;
100 #endif
101 
102  time_t min_ttl;
103  time_t err_ttl;
104  time_t txt_ttl;
105  time_t rdns_ttl;
106 
108 
109 
111 
112 
113 static inline SPF_dns_cache_config_t *SPF_voidp2spfhook( void *hook )
114  { return (SPF_dns_cache_config_t *)hook; }
115 static inline void *SPF_spfhook2voidp( SPF_dns_cache_config_t *spfhook )
116  { return (void *)spfhook; }
117 
118 
119 /*
120 ** calculate CRC-32 stuff.
121 */
122 
123 /*
124  * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
125  * code or tables extracted from it, as desired without restriction.
126  *
127  * First, the polynomial itself and its table of feedback terms. The
128  * polynomial is
129  * 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
130  *
131  * Note that we take it "backwards" and put the highest-order term in
132  * the lowest-order bit. The X^32 term is "implied"; the LSB is the
133  * X^31 term, etc. The X^0 term (usually shown as "+1") results in
134  * the MSB being 1
135  *
136  * Note that the usual hardware shift register implementation, which
137  * is what we're using (we're merely optimizing it by doing eight-bit
138  * chunks at a time) shifts bits into the lowest-order term. In our
139  * implementation, that means shifting towards the right. Why do we
140  * do it this way? Because the calculated CRC must be transmitted in
141  * order from highest-order term to lowest-order term. UARTs transmit
142  * characters in order from LSB to MSB. By storing the CRC this way
143  * we hand it to the UART in the order low-byte to high-byte; the UART
144  * sends each low-bit to hight-bit; and the result is transmission bit
145  * by bit from highest- to lowest-order term without requiring any bit
146  * shuffling on our part. Reception works similarly
147  *
148  * The feedback terms table consists of 256, 32-bit entries. Notes
149  *
150  * The table can be generated at runtime if desired; code to do so
151  * is shown later. It might not be obvious, but the feedback
152  * terms simply represent the results of eight shift/xor opera
153  * tions for all combinations of data and CRC register values
154  *
155  * The values must be right-shifted by eight bits by the "updcrc
156  * logic; the shift must be unsigned (bring in zeroes). On some
157  * hardware you could probably optimize the shift in assembler by
158  * using byte-swap instructions
159  * polynomial $edb88320
160  */
161 
162 const unsigned int crc_32_tab[256] = {
163  0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
164  0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
165  0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
166  0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
167  0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
168  0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
169  0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
170  0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
171  0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
172  0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
173  0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
174  0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
175  0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
176  0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
177  0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
178  0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
179  0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
180  0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
181  0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
182  0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
183  0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
184  0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
185  0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
186  0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
187  0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
188  0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
189  0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
190  0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
191  0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
192  0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
193  0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
194  0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
195  0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
196  0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
197  0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
198  0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
199  0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
200  0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
201  0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
202  0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
203  0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
204  0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
205  0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
206  0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
207  0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
208  0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
209  0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
210  0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
211  0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
212  0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
213  0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
214  0x2d02ef8dL
215 };
216 
217 static inline int
218 crc32str(unsigned int accum, const char *str, int max_hash_len)
219 {
220  for( ; *str != '\0' && max_hash_len > 0; str++ ) {
221  if ( *str == '.' )
222  continue;
223 
224  accum = crc_32_tab[ (unsigned char)accum ^ (unsigned char)*str ]
225  ^ (unsigned char)(accum >> 8);
226 
227  max_hash_len--;
228  }
229 
230 
231  return accum;
232 }
233 
234 // #define hash(h,s,a) (crc32str(a,s,h->max_hash_len) & (h->hash_mask))
235 #define hash(h,s,a) crc32str(a,s,h->max_hash_len)
236 
237 /* This must be called with the lock held. */
238 static SPF_dns_cache_bucket_t *
239 SPF_dns_cache_bucket_find(SPF_dns_cache_config_t *spfhook,
240  const char *domain, ns_type rr_type, int idx)
241 {
242  SPF_dns_cache_bucket_t *bucket;
244  SPF_dns_rr_t *rr;
245  time_t now;
246 
247  bucket = spfhook->cache[idx];
248  prev = NULL;
249  time(&now);
250 
251  while (bucket != NULL) {
252  rr = bucket->rr;
253 
254  if (rr->utc_ttl < now) {
255  /* Unlink the bucket. */
256  if (prev != NULL)
257  prev->next = bucket->next;
258  else
259  spfhook->cache[idx] = bucket->next;
260  /* Free the bucket. */
261  if (bucket->rr)
262  SPF_dns_rr_free(bucket->rr);
263  free(bucket);
264  /* Set iterator back one step. */
265  bucket = prev; /* Might be NULL */
266  }
267  else if (rr->rr_type != rr_type) {
268  /* Types differ */
269  }
270  else if (strcmp(rr->domain, domain) != 0) {
271  /* Domains differ */
272  }
273  else {
274  /* Move the bucket to the top of the chain. */
275  if (prev != NULL) {
276  prev->next = bucket->next;
277  bucket->next = spfhook->cache[idx];
278  spfhook->cache[idx] = bucket;
279  }
280  return bucket;
281  }
282 
283  prev = bucket; /* Might be NULL */
284  if (bucket == NULL) /* After an unlink */
285  bucket = spfhook->cache[idx];
286  else
287  bucket = bucket->next;
288  }
289 
290  return NULL;
291 }
292 
293 /* This must be called with the lock held. */
294 static SPF_errcode_t
295 SPF_dns_cache_bucket_add(SPF_dns_cache_config_t *spfhook,
296  SPF_dns_rr_t *rr, int idx)
297 {
298  SPF_dns_cache_bucket_t *bucket;
299 
300  bucket = (SPF_dns_cache_bucket_t *)
301  malloc(sizeof(SPF_dns_cache_bucket_t));
302  if (! bucket)
303  return SPF_E_NO_MEMORY;
304  bucket->next = spfhook->cache[idx];
305  spfhook->cache[idx] = bucket;
306  bucket->rr = rr;
307  return SPF_E_SUCCESS;
308 }
309 
310 
314 static SPF_errcode_t
315 SPF_dns_cache_rr_fixup(SPF_dns_cache_config_t *spfhook,
316  SPF_dns_rr_t *cached_rr,
317  const char *domain, ns_type rr_type)
318 {
319  char *p;
320 
321  /* make sure the RR has enough data to be useful for caching */
322  if (cached_rr->rr_type == ns_t_any)
323  cached_rr->rr_type = rr_type;
324 
325  /* XXX I'm still not sure about this bit. */
326  if (cached_rr->domain == NULL || cached_rr->domain[0] != '\0') {
327  char *new_domain;
328  size_t new_len = strlen(domain) + 1;
329 
330  if (cached_rr->domain == NULL || cached_rr->domain_buf_len < new_len) {
331  new_domain = realloc(cached_rr->domain, new_len);
332  if (new_domain == NULL)
333  return SPF_E_NO_MEMORY;
334  cached_rr->domain = new_domain;
335  cached_rr->domain_buf_len = new_len;
336  }
337  strcpy(cached_rr->domain, domain);
338  }
339 
340  /* set up the ttl values */
341  if ( cached_rr->ttl < spfhook->min_ttl )
342  cached_rr->ttl = spfhook->min_ttl;
343 
344  if ( cached_rr->ttl < spfhook->txt_ttl
345  && cached_rr->rr_type == ns_t_txt || cached_rr->rr_type == ns_t_spf )
346  cached_rr->ttl = spfhook->txt_ttl;
347 
348  if ( cached_rr->ttl < spfhook->err_ttl
349  && cached_rr->herrno != NETDB_SUCCESS )
350  cached_rr->ttl = spfhook->err_ttl;
351 
352  if ( cached_rr->ttl < spfhook->rdns_ttl ) {
353  p = strstr( cached_rr->domain, ".arpa" );
354  if ( p && p[ sizeof( ".arpa" )-1 ] == '\0' )
355  cached_rr->ttl = spfhook->rdns_ttl;
356  }
357 
358  cached_rr->utc_ttl = cached_rr->ttl + time(NULL);
359 
360  return SPF_E_SUCCESS;
361 }
362 
363 
367 static SPF_dns_rr_t *
368 SPF_dns_cache_lookup(SPF_dns_server_t *spf_dns_server,
369  const char *domain, ns_type rr_type, int should_cache)
370 {
371  SPF_dns_cache_config_t *spfhook;
372  SPF_dns_cache_bucket_t *bucket;
373  SPF_dns_rr_t *cached_rr;
374  SPF_dns_rr_t *rr;
375  int idx;
376 
377  spfhook = SPF_voidp2spfhook(spf_dns_server->hook);
378 
379  /* max_hash_len and cache_size are constant, so this be done
380  * outside the lock. */
381  idx = hash(spfhook, domain, 0 /* spfhook->hash_mask+rr_type */);
382  idx &= (spfhook->cache_size - 1);
383 
384  pthread_mutex_lock(&(spfhook->cache_lock));
385 
386  bucket = SPF_dns_cache_bucket_find(spfhook, domain, rr_type, idx);
387  if (bucket != NULL) {
388  if (bucket->rr != NULL) {
389  if (SPF_dns_rr_dup(&rr, bucket->rr) == SPF_E_SUCCESS) {
390  pthread_mutex_unlock(&(spfhook->cache_lock));
391  return rr;
392  }
393  else if (rr != NULL) {
394  SPF_dns_rr_free(rr); /* Within the lock. :-( */
395  }
396  }
397  }
398 
399  /* Make sure we don't hang onto this outside the lock.
400  * idx is presumably safe. */
401  bucket = NULL;
402 
403  pthread_mutex_unlock(&(spfhook->cache_lock));
404 
405  if (!spf_dns_server->layer_below)
406  return SPF_dns_rr_new_nxdomain(spf_dns_server, domain);
407 
408  rr = SPF_dns_lookup( spf_dns_server->layer_below,
409  domain, rr_type, should_cache );
410  if (spfhook->conserve_cache && !should_cache)
411  return rr;
412 
413  pthread_mutex_lock(&(spfhook->cache_lock));
414 
415  if (SPF_dns_rr_dup(&cached_rr, rr) == SPF_E_SUCCESS) {
416  if (SPF_dns_cache_rr_fixup(spfhook, cached_rr, domain, rr_type) == SPF_E_SUCCESS){
417  if (SPF_dns_cache_bucket_add(spfhook, cached_rr, idx) == SPF_E_SUCCESS) {
418  pthread_mutex_unlock(&(spfhook->cache_lock));
419  return rr;
420  }
421  }
422  }
423 
424  pthread_mutex_unlock(&(spfhook->cache_lock));
425 
426  if (cached_rr)
427  SPF_dns_rr_free(cached_rr);
428 
429  return rr;
430 
431 }
432 
433 
434 static void
435 SPF_dns_cache_free( SPF_dns_server_t *spf_dns_server )
436 {
437  SPF_dns_cache_config_t *spfhook;
438  SPF_dns_cache_bucket_t *bucket;
440  int i;
441 
442  SPF_ASSERT_NOTNULL(spf_dns_server);
443 
444  spfhook = SPF_voidp2spfhook( spf_dns_server->hook );
445  if ( spfhook ) {
446  pthread_mutex_lock(&(spfhook->cache_lock));
447 
448  if (spfhook->cache) {
449  for( i = 0; i < spfhook->cache_size; i++ ) {
450  bucket = spfhook->cache[i];
451  while (bucket != NULL) {
452  prev = bucket;
453  bucket = bucket->next;
454 
455  /* Free the bucket. */
456  if (prev->rr)
457  SPF_dns_rr_free(prev->rr);
458  free(prev);
459  }
460  }
461  free(spfhook->cache);
462  spfhook->cache = NULL;
463  }
464 
465  pthread_mutex_unlock(&(spfhook->cache_lock));
466 
467  /*
468  * There is a risk that something might grab the mutex
469  * here and try to look things up and try to resolve
470  * stuff from a mashed cache it might happen but that's
471  * what you get for trying to simultaneously free and
472  * use a resource destroy will then return EBUSY but
473  * it'll probably segfault so there ain't much to be
474  * done really.
475  */
476  pthread_mutex_destroy(&(spfhook->cache_lock));
477 
478  free(spfhook);
479  }
480 
481  free(spf_dns_server);
482 }
483 
484 
485 
486 SPF_dns_server_t *
487 SPF_dns_cache_new(SPF_dns_server_t *layer_below,
488  const char *name, int debug, int cache_bits)
489 {
490  SPF_dns_server_t *spf_dns_server;
491  SPF_dns_cache_config_t *spfhook;
492 
493  SPF_ASSERT_NOTNULL(layer_below);
494 
495  if ( cache_bits < 1 || cache_bits > 16 )
496  SPF_error( "cache bits out of range (1..16)." );
497 
498 
499  spf_dns_server = malloc(sizeof(SPF_dns_server_t));
500  if (spf_dns_server == NULL)
501  return NULL;
502  memset(spf_dns_server, 0, sizeof(SPF_dns_server_t));
503 
504  spf_dns_server->hook = malloc(sizeof(SPF_dns_cache_config_t));
505  if (spf_dns_server->hook == NULL) {
506  free(spf_dns_server);
507  return NULL;
508  }
509  memset(spf_dns_server->hook, 0, sizeof(SPF_dns_cache_config_t));
510 
511  if (name == NULL)
512  name = "cache";
513 
514  spf_dns_server->destroy = SPF_dns_cache_free;
515  spf_dns_server->lookup = SPF_dns_cache_lookup;
516  spf_dns_server->get_spf = NULL;
517  spf_dns_server->get_exp = NULL;
518  spf_dns_server->add_cache = NULL;
519  spf_dns_server->layer_below = layer_below;
520  spf_dns_server->name = name;
521  spf_dns_server->debug = debug;
522 
523  spfhook = SPF_voidp2spfhook( spf_dns_server->hook );
524 
525  spfhook->cache_size = 1 << cache_bits;
526  spfhook->hash_mask = spfhook->cache_size - 1;
527  spfhook->max_hash_len = cache_bits > 4 ? cache_bits * 2 : 8;
528 
529  spfhook->cache = calloc(spfhook->cache_size,
530  sizeof(*spfhook->cache));
531 
532 #if 0
533  spfhook->hit = 0;
534  spfhook->miss = 0;
535 #endif
536 
537  spfhook->min_ttl = 30;
538  spfhook->err_ttl = 30*60;
539  spfhook->txt_ttl = 30*60;
540  spfhook->rdns_ttl = 30*60;
541  spfhook->conserve_cache = cache_bits < 12;
542 
543  if (spfhook->cache == NULL) {
544  free(spfhook);
545  free(spf_dns_server);
546  return NULL;
547  }
548 
549  pthread_mutex_init(&(spfhook->cache_lock),NULL);
550 
551  return spf_dns_server;
552 }
553 
554 void
555 SPF_dns_cache_set_ttl( SPF_dns_server_t *spf_dns_server,
556  time_t min_ttl, time_t err_ttl,
557  time_t txt_ttl, time_t rdns_ttl )
558 {
559  SPF_dns_cache_config_t *spfhook;
560 
561  SPF_ASSERT_NOTNULL(spf_dns_server);
562 
563  spfhook = SPF_voidp2spfhook( spf_dns_server->hook );
564 
565  if (spfhook != NULL) {
566  pthread_mutex_lock(&(spfhook->cache_lock));
567  spfhook->min_ttl = min_ttl;
568  spfhook->err_ttl = err_ttl;
569  spfhook->txt_ttl = txt_ttl;
570  spfhook->rdns_ttl = rdns_ttl;
571  pthread_mutex_unlock(&(spfhook->cache_lock));
572  }
573 }
574 
575 
576 void
577 SPF_dns_set_conserve_cache( SPF_dns_server_t *spf_dns_server,
578  int conserve_cache )
579 {
580  SPF_dns_cache_config_t *spfhook;
581 
582  SPF_ASSERT_NOTNULL(spf_dns_server);
583 
584  spfhook = SPF_voidp2spfhook( spf_dns_server->hook );
585  /* This is a boolean and it doesn't matter if it
586  * changes suddenly, thus no lock. */
587  if (spfhook != NULL)
588  spfhook->conserve_cache = conserve_cache;
589 }
#define hash(h, s, a)
SPF_errcode_t SPF_dns_rr_dup(SPF_dns_rr_t **dstp, SPF_dns_rr_t *src)
Definition: spf_dns_rr.c:189
#define SPF_ASSERT_NOTNULL(x)
Definition: spf_log.h:118
pthread_mutex_t cache_lock
Definition: spf_dns_cache.c:92
SPF_errcode_t
Definition: spf_response.h:118
#define debug
#define NULL
Definition: spf_internal.h:28
ns_type
Definition: arpa_nameser.h:300
#define ns_t_spf
Definition: spf_dns.h:89
char * domain
Definition: spf_dns_rr.h:53
SPF_dns_stat_t herrno
Definition: spf_dns_rr.h:66
const unsigned int crc_32_tab[256]
void SPF_dns_cache_set_ttl(SPF_dns_server_t *spf_dns_server, time_t min_ttl, time_t err_ttl, time_t txt_ttl, time_t rdns_ttl)
size_t domain_buf_len
Definition: spf_dns_rr.h:54
SPF_dns_rr_t * SPF_dns_lookup(SPF_dns_server_t *spf_dns_server, const char *domain, ns_type rr_type, int should_cache)
Definition: spf_dns.c:133
#define SPF_error(errmsg)
Definition: spf_log.h:40
void SPF_dns_rr_free(SPF_dns_rr_t *spfrr)
Definition: spf_dns_rr.c:114
time_t utc_ttl
Definition: spf_dns_rr.h:65
void SPF_dns_set_conserve_cache(SPF_dns_server_t *spf_dns_server, int conserve_cache)
SPF_dns_cache_bucket_t ** cache
Definition: spf_dns_cache.c:90
ns_type rr_type
Definition: spf_dns_rr.h:56
struct _SPF_dns_cache_bucket_t * next
Definition: spf_dns_cache.c:84
time_t ttl
Definition: spf_dns_rr.h:64
#define NETDB_SUCCESS
Definition: spf_dns.h:102
SPF_dns_server_t * SPF_dns_cache_new(SPF_dns_server_t *layer_below, const char *name, int debug, int cache_bits)
SPF_dns_rr_t * SPF_dns_rr_new_nxdomain(SPF_dns_server_t *spf_dns_server, const char *domain)
Definition: spf_dns_rr.c:53