4 * resolver/dns related functions, dns cache and failover
6 * Copyright (C) 2006 iptelorg GmbH
8 * This file is part of ser, a free SIP server.
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
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:
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.
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
31 * 2006-07-13 created by andrei
32 * 2007-06-16 naptr support (andrei)
33 * 2007-07-30 DNS cache measurements added (Gergo)
41 #include "config.h" /* MAX_BRANCHES */
44 #include "atomic_ops.h"
48 #if defined(USE_DNS_FAILOVER) && !defined(USE_DNS_CACHE)
49 #error "DNS FAILOVER requires DNS CACHE support (define USE_DNS_CACHE)"
52 #if defined(DNS_WATCHDOG_SUPPORT) && !defined(USE_DNS_CACHE)
53 #error "DNS WATCHDOG requires DNS CACHE support (define USE_DNS_CACHE)"
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 */
61 /* uncomment the define below for SRV weight based load balancing */
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
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 */,
79 E_DNS_NO_SRV /* unresolvable srv record */,
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
88 E_DNS_NO_NAPTR /* unresolvable naptr record */,
89 E_DNS_CRITICAL /* critical error, marks the end
90 of the error table (always last) */
95 /* return a short string, printable error description (err <=0) */
96 const char* dns_strerror(int err);
98 /* dns entry error flags */
99 #define DNS_BAD_NAME 1 /* unresolvable */
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 */
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 */
117 /* stripped down dns rr */
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 */
130 struct dns_lu_lst{ /* last used ordered list */
131 struct dns_lu_lst* next;
132 struct dns_lu_lst* prev;
136 struct dns_hash_entry{
137 /* hash table links */
138 struct dns_hash_entry* next;
139 struct dns_hash_entry* prev;
141 struct dns_lu_lst last_used_lst;
143 struct dns_rr* rr_lst;
146 ticks_t expire; /* when the whole entry will expire */
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)*/
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;
162 typedef unsigned long long srv_flags_t;
165 struct dns_srv_handle{
166 struct dns_hash_entry* srv; /* srv entry */
167 struct dns_hash_entry* a; /* a or aaaa current entry */
169 srv_flags_t srv_tried_rrs;
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 */
179 const char* dns_strerror(int err);
181 void fix_dns_flags(str *name);
182 int use_dns_failover_fixup(void *handle, str *name, void **val);
183 int dns_cache_max_mem_fixup(void *handle, str *name, void **val);
184 int init_dns_cache();
185 #ifdef USE_DNS_CACHE_STATS
186 int init_dns_cache_stats(int iproc_num);
187 #define DNS_CACHE_ALL_STATS "dc_all_stats"
189 void destroy_dns_cache();
192 void dns_hash_put(struct dns_hash_entry* e);
193 void dns_hash_put_shm_unsafe(struct dns_hash_entry* e);
195 inline static void dns_srv_handle_put(struct dns_srv_handle* h)
199 dns_hash_put(h->srv);
211 /* use it when copying, it manually increases the ref cound */
212 inline static void dns_srv_handle_ref(struct dns_srv_handle *h)
216 atomic_inc(&h->srv->refcnt);
218 atomic_inc(&h->a->refcnt);
224 /* safe copy increases the refcnt, src must not change while in this function
225 * WARNING: the copy must be dns_srv_handle_put ! */
226 inline static void dns_srv_handle_cpy(struct dns_srv_handle* dst,
227 struct dns_srv_handle* src)
229 dns_srv_handle_ref(src);
235 /* same as above but assume shm_lock held (for internal tm use only) */
236 inline static void dns_srv_handle_put_shm_unsafe(struct dns_srv_handle* h)
240 dns_hash_put_shm_unsafe(h->srv);
244 dns_hash_put_shm_unsafe(h->a);
252 /* get "next" ip next time a dns_srv_handle function is called
253 * params: h - struct dns_srv_handler
254 * err - return code of the last dns_*_resolve* call
255 * returns: 0 if it doesn't make sense to try another record,
258 inline static int dns_srv_handle_next(struct dns_srv_handle* h, int err)
262 return (h->srv || h->a);
267 inline static void dns_srv_handle_init(struct dns_srv_handle* h)
270 h->srv_no=h->ip_no=0;
280 /* performes a srv query on name
281 * Params: name - srv query target (e.g. _sip._udp.foo.bar)
282 * ip - result: first good ip found
283 * port - result: corresponding port number
284 * flags - resolve options (like ipv4 only, ipv6 prefered a.s.o)
285 * Returns: < 0 on error (can be passed to dns_strerror(), 0 on success
287 int dns_srv_get_ip(str* name, struct ip_addr* ip, unsigned short* port,
290 /* performs an A, AAAA (or both) query/queries
291 * Params: name - query target (e.g. foo.bar)
292 * ip - result: first good ip found
293 * flags - resolve options (like ipv4 only, ipv6 prefered a.s.o)
294 * Returns: < 0 on error (can be passed to dns_strerror(), 0 on success
296 int dns_get_ip(str* name, struct ip_addr* ip, int flags);
298 struct hostent* dns_srv_get_he(str* name, unsigned short* port, int flags);
299 struct hostent* dns_get_he(str* name, int flags);
302 /* resolve name to an ip, using srv record. Can be called multiple times
303 * to iterate on all the possible ips, e.g :
304 * dns_srv_handle_init(h);
305 * ret_code=dns_sip_resolve(h,...);
306 * while( dns_srv_handle_next(h, ret_code){ ret_code=dns_sip_resolve(h...); }
307 * dns_srv_handle_put(h);
308 * WARNING: dns_srv_handle_init() must be called to initialize h and
309 * dns_srv_handle_put(h) must be called when h is no longer needed
311 int dns_sip_resolve(struct dns_srv_handle* h, str* name, struct ip_addr* ip,
312 unsigned short* port, char* proto, int flags);
314 /* same as above, but fills su intead of changing port and filling an ip */
315 inline static int dns_sip_resolve2su(struct dns_srv_handle* h,
316 union sockaddr_union* su,
317 str* name, unsigned short port,
318 char* proto, int flags)
323 ret=dns_sip_resolve(h, name, &ip, &port, proto, flags);
325 init_su(su, &ip, port);
329 /* deletes all the entries from the cache */
330 void dns_cache_flush(void);
332 #ifdef DNS_WATCHDOG_SUPPORT
333 /* sets the state of the DNS servers:
334 * 1: at least one server is up
335 * 0: all the servers are down
337 void dns_set_server_state(int state);
339 /* returns the state of the DNS servers */
340 int dns_get_server_state(void);
341 #endif /* DNS_WATCHDOG_SUPPORT */