Merge '/scripts' of kamailio svn into sip-router/tools
[sip-router] / dns_cache.h
1 /*
2  * $Id$
3  *
4  * resolver/dns related functions, dns cache and failover
5  *
6  * Copyright (C) 2006 iptelorg GmbH
7  *
8  * This file is part of ser, a free SIP server.
9  *
10  * ser is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version
14  *
15  * For a license to use the ser software under conditions
16  * other than those described here, or to purchase support for this
17  * software, please contact iptel.org by e-mail at the following addresses:
18  *    info@iptel.org
19  *
20  * ser is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program; if not, write to the Free Software
27  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
28  */
29 /* History:
30  * --------
31  *  2006-07-13  created by andrei
32  *  2007-06-16  naptr support (andrei)
33  *  2007-07-30  DNS cache measurements added (Gergo)
34  */
35
36
37 #ifndef __dns_cache_h
38 #define __dns_cache_h
39
40 #include "str.h"
41 #include "config.h" /* MAX_BRANCHES */
42 #include "timer.h"
43 #include "ip_addr.h"
44 #include "atomic_ops.h"
45 #include "resolve.h"
46
47
48 #if defined(USE_DNS_FAILOVER) && !defined(USE_DNS_CACHE)
49 #error "DNS FAILOVER requires DNS CACHE support (define USE_DNS_CACHE)"
50 #endif
51
52 #if defined(DNS_WATCHDOG_SUPPORT) && !defined(USE_DNS_CACHE)
53 #error "DNS WATCHDOG requires DNS CACHE support (define USE_DNS_CACHE)"
54 #endif
55
56 #define DEFAULT_DNS_NEG_CACHE_TTL 60 /* 1 min. */
57 #define DEFAULT_DNS_CACHE_MIN_TTL 0 /* (disabled) */
58 #define DEFAULT_DNS_CACHE_MAX_TTL ((unsigned int)(-1)) /* (maxint) */
59 #define DEFAULT_DNS_MAX_MEM 500 /* 500 Kb */
60
61 /* uncomment the define below for SRV weight based load balancing */
62 #define DNS_SRV_LB
63
64 #define DNS_LU_LST
65
66 /* dns functions return them as negative values (e.g. return -E_DNS_NO_IP)
67  * listed in the order of importance ( if more errors, only the most important
68  * is returned)
69  */
70 enum dns_errors{
71                                         E_DNS_OK=0,
72                                         E_DNS_EOR, /* no more records (not an error)
73                                                       -- returned only by the dns_resolve*
74                                                                   functions when called iteratively,; it
75                                                                   signals the end of the ip/records list */
76                                         E_DNS_UNKNOWN /* unkown error */,
77                                         E_DNS_INTERNAL_ERR /* internal error */,
78                                         E_DNS_BAD_SRV_ENTRY,
79                                         E_DNS_NO_SRV /* unresolvable srv record */,
80                                         E_DNS_BAD_IP_ENTRY,
81                                         E_DNS_NO_IP /* unresolvable a or aaaa records*/,
82                                         E_DNS_BAD_IP /* the ip is invalid */,
83                                         E_DNS_BLACKLIST_IP /* the ip is blacklisted */,
84                                         E_DNS_NAME_TOO_LONG /* try again with a shorter name */,
85                                         E_DNS_AF_MISMATCH /* ipv4 or ipv6 only requested, but
86                                                                                  name contains an ip addr. of the
87                                                                                  opossite type */ ,
88                                         E_DNS_NO_NAPTR /* unresolvable naptr record */,
89                                         E_DNS_CRITICAL /* critical error, marks the end
90                                                                           of the error table (always last) */
91 };
92
93
94
95 /* return a short string, printable error description (err <=0) */
96 const char* dns_strerror(int err);
97
98 /* dns entry error flags */
99 #define DNS_BAD_NAME     1 /* unresolvable */
100
101 /* dns requests flags */
102 #define DNS_NO_FLAGS    0
103 #define DNS_IPV4_ONLY   1
104 #define DNS_IPV6_ONLY   2
105 #define DNS_IPV6_FIRST  4
106 #define DNS_SRV_RR_LB   8  /* SRV RR weight based load balancing */
107 #define DNS_TRY_NAPTR   16 /* enable naptr lookup */
108
109
110 /* ip blacklist error flags */
111 #define IP_ERR_BAD_DST      2 /* destination is marked as bad (e.g. bad ip) */
112 #define IP_ERR_SND          3 /* send error while using this as destination */
113 #define IP_ERR_TIMEOUT      4 /* timeout waiting for a response */
114 #define IP_ERR_TCP_CON      5 /* could not establish tcp connection */
115
116
117 /* stripped down dns rr */
118 struct dns_rr{
119         struct dns_rr* next;
120         void* rdata; /* depends on the type */
121         /* name, type and class are not needed, contained in struct dns_query */
122         ticks_t expire; /* = ttl + crt_time */
123         unsigned char err_flags; /* if 0 everything is ok */
124
125 };
126
127
128
129 #ifdef DNS_LU_LST
130 struct dns_lu_lst{  /* last used ordered list */
131         struct dns_lu_lst* next;
132         struct dns_lu_lst* prev;
133 };
134 #endif
135
136 struct dns_hash_entry{
137         /* hash table links */
138         struct dns_hash_entry* next;
139         struct dns_hash_entry* prev;
140 #ifdef DNS_LU_LST
141         struct dns_lu_lst last_used_lst;
142 #endif
143         struct dns_rr* rr_lst;
144         atomic_t refcnt;
145         ticks_t last_used;
146         ticks_t expire; /* when the whole entry will expire */
147         int total_size;
148         unsigned short type;
149         unsigned char err_flags;
150         unsigned char name_len; /* can be maximum 255 bytes */
151         char name[1]; /* variable length, name, null terminated
152                          (actual lenght = name_len +1)*/
153 };
154
155
156 #if MAX_BRANCHES < 16
157 /* forking is limited by tm to 12 by default */
158 typedef unsigned short srv_flags_t;
159 #elif MAX_BRANCHES < 32
160 typedef unsigned int srv_flags_t;
161 #else
162 typedef unsigned long long srv_flags_t;
163 #endif
164
165 struct dns_srv_handle{
166         struct dns_hash_entry* srv; /* srv entry */
167         struct dns_hash_entry* a;   /* a or aaaa current entry */
168 #ifdef DNS_SRV_LB
169         srv_flags_t srv_tried_rrs;
170 #endif
171         unsigned short port; /* current port */
172         unsigned char srv_no; /* current record no. in the srv entry */
173         unsigned char ip_no;  /* current record no. in the a/aaaa entry */
174         unsigned char proto;  /* protocol number */
175 };
176
177
178
179 const char* dns_strerror(int err);
180
181 void fix_dns_flags(str *gname, str *name);
182 int use_dns_failover_fixup(void *handle, str *gname, str *name, void **val);
183 int use_dns_cache_fixup(void *handle, str *gname, str *name, void **val);
184 int dns_cache_max_mem_fixup(void *handle, str *gname, str *name, void **val);
185 int init_dns_cache();
186 #ifdef USE_DNS_CACHE_STATS
187 int init_dns_cache_stats(int iproc_num);
188 #define DNS_CACHE_ALL_STATS "dc_all_stats"
189 #endif
190 void destroy_dns_cache();
191
192
193 void dns_hash_put(struct dns_hash_entry* e);
194 void dns_hash_put_shm_unsafe(struct dns_hash_entry* e);
195
196 inline static void dns_srv_handle_put(struct dns_srv_handle* h)
197 {
198         if (h){
199                 if (h->srv){
200                         dns_hash_put(h->srv);
201                         h->srv=0;
202                 }
203                 if (h->a){
204                         dns_hash_put(h->a);
205                         h->a=0;
206                 }
207         }
208 }
209
210
211
212 /* use it when copying, it manually increases the ref cound */
213 inline static void dns_srv_handle_ref(struct dns_srv_handle *h)
214 {
215         if (h){
216                 if (h->srv)
217                         atomic_inc(&h->srv->refcnt);
218                 if (h->a)
219                         atomic_inc(&h->a->refcnt);
220         }
221 }
222
223
224
225 /* safe copy increases the refcnt, src must not change while in this function
226  * WARNING: the copy must be dns_srv_handle_put ! */
227 inline static void dns_srv_handle_cpy(struct dns_srv_handle* dst,
228                                                                                 struct dns_srv_handle* src)
229 {
230         dns_srv_handle_ref(src);
231         *dst=*src;
232 }
233
234
235
236 /* same as above but assume shm_lock held (for internal tm use only) */
237 inline static void dns_srv_handle_put_shm_unsafe(struct dns_srv_handle* h)
238 {
239         if (h){
240                 if (h->srv){
241                         dns_hash_put_shm_unsafe(h->srv);
242                         h->srv=0;
243                 }
244                 if (h->a){
245                         dns_hash_put_shm_unsafe(h->a);
246                         h->a=0;
247                 }
248         }
249 }
250
251
252
253 /* get "next" ip next time a dns_srv_handle function is called
254  * params: h   - struct dns_srv_handler
255  *         err - return code of the last dns_*_resolve* call
256  * returns: 0 if it doesn't make sense to try another record,
257  * 1 otherwise
258  */
259 inline static int dns_srv_handle_next(struct dns_srv_handle* h, int err)
260 {
261         if (err<0) return 0;
262         h->ip_no++;
263         return (h->srv || h->a);
264 }
265
266
267
268 inline static void dns_srv_handle_init(struct dns_srv_handle* h)
269 {
270         h->srv=h->a=0;
271         h->srv_no=h->ip_no=0;
272         h->port=0;
273         h->proto=0;
274 #ifdef DNS_SRV_LB
275         h->srv_tried_rrs=0;
276 #endif
277 }
278
279
280
281 /* performes a srv query on name
282  * Params:  name  - srv query target (e.g. _sip._udp.foo.bar)
283  *          ip    - result: first good ip found
284  *          port  - result: corresponding port number
285  *          flags - resolve options (like ipv4 only, ipv6 prefered a.s.o)
286  * Returns: < 0 on error (can be passed to dns_strerror(), 0 on success
287  */
288 int dns_srv_get_ip(str* name, struct ip_addr* ip, unsigned short* port,
289                                         int flags);
290
291 /* performs an A, AAAA (or both) query/queries
292  * Params:  name  - query target (e.g. foo.bar)
293  *          ip    - result: first good ip found
294  *          flags - resolve options (like ipv4 only, ipv6 prefered a.s.o)
295  * Returns: < 0 on error (can be passed to dns_strerror(), 0 on success
296  */
297 int dns_get_ip(str* name, struct ip_addr* ip, int flags);
298
299 struct hostent* dns_srv_get_he(str* name, unsigned short* port, int flags);
300 struct hostent* dns_get_he(str* name, int flags);
301
302
303 /* resolve name to an ip, using srv record. Can be called multiple times
304  * to iterate on all the possible ips, e.g :
305  * dns_srv_handle_init(h);
306  * ret_code=dns_sip_resolve(h,...);
307  *  while( dns_srv_handle_next(h, ret_code){ ret_code=dns_sip_resolve(h...); }
308  * dns_srv_handle_put(h);
309  * WARNING: dns_srv_handle_init() must be called to initialize h and
310  *  dns_srv_handle_put(h) must be called when h is no longer needed
311  */
312 int dns_sip_resolve(struct dns_srv_handle* h,  str* name, struct ip_addr* ip,
313                                         unsigned short* port, char* proto, int flags);
314
315 /* same as above, but fills su intead of changing port and filling an ip */
316 inline static int dns_sip_resolve2su(struct dns_srv_handle* h,
317                                                                          union sockaddr_union* su,
318                                                                          str* name, unsigned short port,
319                                                                          char* proto, int flags)
320 {
321         struct ip_addr ip;
322         int ret;
323
324         ret=dns_sip_resolve(h, name, &ip, &port, proto, flags);
325         if (ret>=0)
326                 init_su(su, &ip, port);
327         return ret;
328 }
329
330 /* deletes all the entries from the cache */
331 void dns_cache_flush(void);
332
333 #ifdef DNS_WATCHDOG_SUPPORT
334 /* sets the state of the DNS servers:
335  * 1: at least one server is up
336  * 0: all the servers are down
337  */
338 void dns_set_server_state(int state);
339
340 /* returns the state of the DNS servers */
341 int dns_get_server_state(void);
342 #endif /* DNS_WATCHDOG_SUPPORT */
343
344 #endif