1 /* cache.h - Definitions for the dns cache
2
3 Copyright (C) 2000 Thomas Moestl
4 Copyright (C) 2003, 2004, 2005, 2010, 2011 Paul A. Rombouts
5
6 This file is part of the pdnsd package.
7
8 pdnsd is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
13 pdnsd is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with pdnsd; see the file COPYING. If not, see
20 <http://www.gnu.org/licenses/>.
21 */
22
23
24 #ifndef _CACHE_H_
25 #define _CACHE_H_
26
27 #include <config.h>
28 #include "ipvers.h"
29 #include <stdio.h>
30 #include "list.h"
31 #include "dns.h"
32 #include "conff.h"
33
34 struct rr_lent_s;
35
36 /*
37 * These values are converted to host byte order. the data is _not_.
38 */
39 typedef struct rr_b_s {
40 struct rr_b_s *next; /* this is the next pointer in the dns_cent_t list. */
41 unsigned rdlen;
42 #if ALLOW_LOCAL_AAAA || defined(ENABLE_IPV6)
43 struct in6_addr data[0]; /* dummy for alignment */
44 #else
45 struct in_addr data[0];
46 #endif
47 } rr_bucket_t;
48
49 typedef struct {
50 struct rr_lent_s *lent; /* this points to the list entry */
51 time_t ttl;
52 time_t ts;
53 unsigned short flags;
54 rr_bucket_t *rrs;
55 } rr_set_t;
56
57
58 typedef struct {
59 unsigned char *qname; /* Name of the domain in length byte - string notation. */
60 size_t cs; /* Size of the cache entry, including RR sets. */
61 unsigned short num_rrs; /* The number of RR sets. When this decreases to 0, the cent is deleted. */
62 unsigned short flags; /* Flags for the whole domain. */
63 union {
64 struct { /* Fields used only for negatively cached domains. */
65 struct rr_lent_s *lent; /* list entry for the whole cent. */
66 time_t ttl; /* TTL for negative caching. */
67 time_t ts; /* Timestamp. */
68 } neg;
69 struct { /* Fields used only for domains that actually exist. */
70 rr_set_t *(rrmu[NRRMU]); /* The most used records.
71 Use the the value obtained from rrlkuptab[] as index. */
72 rr_set_t **rrext; /* Pointer (may be NULL) to an array of size NNRREXT storing the
73 less frequently used records. */
74 } rr;
75 };
76 unsigned char c_ns,c_soa; /* Number of trailing name elements in qname to use to find NS or SOA
77 records to add to the authority section of a response. */
78 } dns_cent_t;
79
80 /* This value is used to represent an undefined c_ns or c_soa field. */
81 #define cundef 0xff
82
83 /*
84 * the flag values for RR sets in the cache
85 */
86 #define CF_NEGATIVE 1 /* this one is for per-RRset negative caching*/
87 #define CF_LOCAL 2 /* Local zone entry */
88 #define CF_AUTH 4 /* authoritative record */
89 #define CF_NOCACHE 8 /* Only hold for the cache latency time period, then purge.
90 * Not really written to cache, but used by add_cache. */
91 #define CF_ADDITIONAL 16 /* This was fetched as an additional or "off-topic" record. */
92 #define CF_NOPURGE 32 /* Do not purge this record */
93 #define CF_ROOTSERV 64 /* This record was directly obtained from a root server */
94
95 #define CFF_NOINHERIT (CF_LOCAL|CF_AUTH|CF_ADDITIONAL|CF_ROOTSERV) /* not to be inherited on requery */
96
97 /*
98 * the flag values for whole domains in the cache
99 */
100 #define DF_NEGATIVE 1 /* this one is for whole-domain negative caching (created on NXDOMAIN)*/
101 #define DF_LOCAL 2 /* local record (in conj. with DF_NEGATIVE) */
102 #define DF_AUTH 4 /* authoritative record */
103 #define DF_NOCACHE 8 /* Only hold for the cache latency time period, then purge.
104 * Only used for negatively cached domains.
105 * Not really written to cache, but used by add_cache. */
106 #define DF_WILD 16 /* subdomains of this domain have wildcard records */
107
108 /* #define DFF_NOINHERIT (DF_NEGATIVE) */ /* not to be inherited on requery */
109
110 enum {w_wild=1, w_neg, w_locnerr}; /* Used to distinguish different types of wildcard records. */
111
112 #if DEBUG>0
113 #define NCFLAGS 7
114 #define NDFLAGS 5
115 #define CFLAGSTRLEN (NCFLAGS*4)
116 #define DFLAGSTRLEN (NDFLAGS*4)
117 extern const char cflgnames[];
118 extern const char dflgnames[];
119 char *flags2str(unsigned flags,char *buf,int nflags,const char *flgnames);
120 #define cflags2str(flags,buf) flags2str(flags,buf,NCFLAGS,cflgnames)
121 #define dflags2str(flags,buf) flags2str(flags,buf,NDFLAGS,dflgnames)
122 #endif
123
124 /*
125 * This is the time in secs any record remains at least in the cache before it is purged.
126 * (exception is that the cache is full)
127 */
128 #define CACHE_LAT 120
129 #define CLAT_ADJ(ttl) ((ttl)<CACHE_LAT?CACHE_LAT:(ttl))
130 /* This is used internally to check if a rrset has timed out. */
131 #define timedout(rrset) ((rrset)->ts+CLAT_ADJ((rrset)->ttl)<time(NULL))
132 /* This is used internally to check if a negatively cached domain has timed out.
133 Only use if the DF_NEGATIVE bit is set! */
134 #define timedout_nxdom(cent) ((cent)->neg.ts+CLAT_ADJ((cent)->neg.ttl)<time(NULL))
135
136 extern volatile short int use_cache_lock;
137
138
139 #ifdef ALLOC_DEBUG
140 #define DBGPARAM ,int dbg
141 #define DBGARG ,dbg
142 #define DBG0 ,0
143 #define DBG1 ,1
144 #else
145 #define DBGPARAM
146 #define DBGARG
147 #define DBG0
148 #define DBG1
149 #endif
150
151
152 /* Initialize the cache. Call only once. */
153 #define init_cache mk_dns_hash
154
155 /* Initialize the cache lock. Call only once. */
156 inline static void init_cache_lock() __attribute__((always_inline));
init_cache_lock()157 inline static void init_cache_lock()
158 {
159 use_cache_lock=1;
160 }
161
162 int empty_cache(slist_array sla);
163 void destroy_cache(void);
164 void read_disk_cache(void);
165 void write_disk_cache(void);
166
167 int report_cache_stat(int f);
168 int dump_cache(int fd, const unsigned char *name, int exact);
169
170 /*
171 * add_cache expects the dns_cent_t to be filled.
172 */
173 void add_cache(dns_cent_t *cent);
174 int add_reverse_cache(dns_cent_t * cent);
175 void del_cache(const unsigned char *name);
176 void invalidate_record(const unsigned char *name);
177 int set_cent_flags(const unsigned char *name, unsigned flags);
178 unsigned char *getlocalowner(unsigned char *name,int tp);
179 dns_cent_t *lookup_cache(const unsigned char *name, int *wild);
180 rr_set_t *lookup_cache_local_rrset(const unsigned char *name, int type);
181 #if 0
182 int add_cache_rr_add(const unsigned char *name, int tp, time_t ttl, time_t ts, unsigned flags, unsigned dlen, void *data, unsigned long serial);
183 #endif
184
185 inline static unsigned int mk_flag_val(servparm_t *server)
186 __attribute__((always_inline));
mk_flag_val(servparm_t * server)187 inline static unsigned int mk_flag_val(servparm_t *server)
188 {
189 unsigned int fl=0;
190 if (!server->purge_cache)
191 fl|=CF_NOPURGE;
192 if (server->nocache)
193 fl|=CF_NOCACHE;
194 if (server->rootserver)
195 fl|=CF_ROOTSERV;
196 return fl;
197 }
198
199 int init_cent(dns_cent_t *cent, const unsigned char *qname, time_t ttl, time_t ts, unsigned flags DBGPARAM);
200 int add_cent_rrset_by_type(dns_cent_t *cent, int type, time_t ttl, time_t ts, unsigned flags DBGPARAM);
201 int add_cent_rr(dns_cent_t *cent, int type, time_t ttl, time_t ts, unsigned flags,unsigned dlen, void *data DBGPARAM);
202 int del_rrset(rr_set_t *rrs DBGPARAM);
203 void free_cent(dns_cent_t *cent DBGPARAM);
204 void free_cent0(void *ptr);
205 void negate_cent(dns_cent_t *cent, time_t ttl, time_t ts);
206 void del_cent(dns_cent_t *cent);
207
208 /* Because this is empty by now, it is defined as an empty macro to save overhead.*/
209 /*void free_rr(rr_bucket_t cent);*/
210 #define free_rr(x)
211
212 dns_cent_t *copy_cent(dns_cent_t *cent DBGPARAM);
213
214 #if 0
215 unsigned long get_serial(void);
216 #endif
217
218 /* Get pointer to rrset given cache entry and rr type value. */
219 inline static rr_set_t *getrrset(dns_cent_t *cent, int type)
220 __attribute__((always_inline));
getrrset(dns_cent_t * cent,int type)221 inline static rr_set_t *getrrset(dns_cent_t *cent, int type)
222 {
223 if(!(cent->flags&DF_NEGATIVE)) {
224 int tpi= type - T_MIN;
225
226 if(tpi>=0 && tpi<T_NUM) {
227 unsigned int idx = rrlkuptab[tpi];
228 if(idx < NRRMU)
229 return cent->rr.rrmu[idx];
230 else {
231 idx -= NRRMU;
232 if(idx < NRREXT) {
233 rr_set_t **rrext= cent->rr.rrext;
234 if(rrext)
235 return rrext[idx];
236 }
237 }
238 }
239 }
240
241 return NULL;
242 }
243
244 /* This version of getrrset is slightly more efficient,
245 but also more dangerous, because it performs less checks.
246 It is safe to use if T_MIN <= type <= T_MAX and cent
247 is not negative.
248 */
249 inline static rr_set_t *getrrset_eff(dns_cent_t *cent, int type)
250 __attribute__((always_inline));
getrrset_eff(dns_cent_t * cent,int type)251 inline static rr_set_t *getrrset_eff(dns_cent_t *cent, int type)
252 {
253 unsigned int idx = rrlkuptab[type-T_MIN];
254 if(idx < NRRMU)
255 return cent->rr.rrmu[idx];
256 else {
257 idx -= NRRMU;
258 if(idx < NRREXT) {
259 rr_set_t **rrext= cent->rr.rrext;
260 if(rrext)
261 return rrext[idx];
262 }
263 }
264
265 return NULL;
266 }
267
268
269 /* have_rr() tests whether a cache entry has at least one record of a given type.
270 Only use if T_MIN <= type <=T_MAX
271 */
272 inline static int have_rr(dns_cent_t *cent, int type)
273 __attribute__((always_inline));
have_rr(dns_cent_t * cent,int type)274 inline static int have_rr(dns_cent_t *cent, int type)
275 {
276 rr_set_t *rrset;
277 return !(cent->flags&DF_NEGATIVE) && (rrset=getrrset_eff(cent, type)) && rrset->rrs;
278 }
279
280 /* Some quick and dirty and hopefully fast macros. */
281 #define PDNSD_NOT_CACHED_TYPE(type) ((type)<T_MIN || (type)>T_MAX || rrlkuptab[(type)-T_MIN]>=NRRTOT)
282
283 /* This is useful for iterating over all the RR types in a cache entry in strict ascending order. */
284 #define NRRITERLIST(cent) ((cent)->flags&DF_NEGATIVE?0:(cent)->rr.rrext?NRRTOT:NRRMU)
285 #define RRITERLIST(cent) ((cent)->flags&DF_NEGATIVE?NULL:(cent)->rr.rrext?rrcachiterlist:rrmuiterlist)
286
287 /* The following macros use array indices as arguments, not RR type values! */
288 #define GET_RRSMU(cent,i) (!((cent)->flags&DF_NEGATIVE)?(cent)->rr.rrmu[i]:NULL)
289 #define GET_RRSEXT(cent,i) (!((cent)->flags&DF_NEGATIVE) && (cent)->rr.rrext?(cent)->rr.rrext[i]:NULL)
290 #define HAVE_RRMU(cent,i) (!((cent)->flags&DF_NEGATIVE) && (cent)->rr.rrmu[i] && (cent)->rr.rrmu[i]->rrs)
291 #define HAVE_RREXT(cent,i) (!((cent)->flags&DF_NEGATIVE) && (cent)->rr.rrext && (cent)->rr.rrext[i] && (cent)->rr.rrext[i]->rrs)
292
293 #define RRARR_LEN(cent) ((cent)->flags&DF_NEGATIVE?0:(cent)->rr.rrext?NRRTOT:NRRMU)
294
295 /* This allows us to index the RR-set arrays in a cache entry as if they formed one contiguous array. */
296 #define RRARR_INDEX_TESTEXT(cent,i) ((cent)->flags&DF_NEGATIVE?NULL:(i)<NRRMU?(cent)->rr.rrmu[i]:(cent)->rr.rrext?(cent)->rr.rrext[(i)-NRRMU]:NULL)
297 /* This gets the address where the pointer to an RR-set is stored in a cache entry,
298 given the cache entry and an RR-set index.
299 Address may be NULL if no storage space for the type has been allocated. */
300 #define RRARR_INDEX_PA_TESTEXT(cent,i) ((cent)->flags&DF_NEGATIVE?NULL:(i)<NRRMU?&(cent)->rr.rrmu[i]:(cent)->rr.rrext?&(cent)->rr.rrext[(i)-NRRMU]:NULL)
301
302 /* The following macros should only be used if 0 <= i < RRARR_LEN(cent) ! */
303 #define RRARR_INDEX(cent,i) ((i)<NRRMU?(cent)->rr.rrmu[i]:(cent)->rr.rrext[(i)-NRRMU])
304 #define RRARR_INDEX_PA(cent,i) ((i)<NRRMU?&(cent)->rr.rrmu[i]:&(cent)->rr.rrext[(i)-NRRMU])
305
306 #endif
307