1 /*
2  * resolver related functions
3  *
4  * Copyright (C) 2001-2003 FhG Fokus
5  *
6  * This file is part of Kamailio, a free SIP server.
7  *
8  * Kamailio 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 2 of the License, or
11  * (at your option) any later version
12  *
13  * Kamailio 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 this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21  */
22 
23 /*!
24  * \file
25  * \brief Kamailio core :: DNS resolver
26  * \author andrei
27  * \ingroup core
28  * Module: \ref core
29  */
30 
31 #ifndef __resolve_h
32 #define __resolve_h
33 
34 #include <sys/types.h>
35 #include <sys/socket.h>
36 #include <netinet/in.h>
37 #include <netdb.h>
38 #include <arpa/nameser.h>
39 #include <resolv.h>
40 #include "counters.h"
41 #include "dns_func.h"
42 
43 #ifdef __OS_darwin
44 #include <arpa/nameser_compat.h>
45 #endif
46 
47 #include "ip_addr.h"
48 #ifdef USE_DNS_CACHE
49 #include "dns_wrappers.h"
50 #endif
51 
52 
53 #define MAX_QUERY_SIZE 8192
54 #define ANS_SIZE       8192
55 #define DNS_HDR_SIZE     12
56 #define MAX_DNS_NAME 256
57 #define MAX_DNS_STRING 255
58 
59 #ifndef T_EBL
60 /** not official yet - iEnum. */
61 #define T_EBL 65300
62 #endif
63 
64 /* get_record flags */
65 #define RES_ONLY_TYPE 1   /* return only the specified type records */
66 #define RES_AR		  2   /* return also the additional records */
67 
68 /* counter for failed/slow DNS requests
69 */
70 struct dns_counters_h {
71     counter_handle_t failed_dns_req;
72     counter_handle_t slow_dns_req;
73 };
74 
75 extern struct dns_counters_h dns_cnts_h;
76 extern struct dns_func_t dns_func;
77 
78 /* query union*/
79 union dns_query{
80 	HEADER hdr;
81 	unsigned char buff[MAX_QUERY_SIZE];
82 };
83 
84 
85 /* rdata struct*/
86 struct rdata {
87 	unsigned short type;
88 	unsigned short pclass;
89 	unsigned int   ttl;
90 	void* rdata;
91 	struct rdata* next;
92 	unsigned char name_len; /* name length w/o the terminating 0 */
93 	char name[1]; /* null terminated name (len=name_len+1) */
94 };
95 /* real size of the structure */
96 #define RDATA_SIZE(s) (sizeof(struct rdata)+(s).name_len) /* +1-1 */
97 
98 
99 /* srv rec. struct*/
100 struct srv_rdata {
101 	unsigned short priority;
102 	unsigned short weight;
103 	unsigned short port;
104 	unsigned char name_len; /* name length w/o the terminating 0 */
105 	char name[1]; /* null terminated name (len=name_len+1) */
106 };
107 
108 
109 /* real size of the structure */
110 #define SRV_RDATA_SIZE(s) (sizeof(struct srv_rdata)+(s).name_len)
111 
112 /* naptr rec. struct*/
113 struct naptr_rdata {
114 	char* flags;    /* points inside str_table */
115 	char* services; /* points inside str_table */
116 	char* regexp;   /* points inside str_table */
117 	char* repl;     /* points inside str_table, null terminated */
118 
119 	unsigned short order;
120 	unsigned short pref;
121 
122 	unsigned char flags_len;
123 	unsigned char services_len;
124 	unsigned char regexp_len;
125 	unsigned char repl_len; /* not currently used */
126 	unsigned char skip_record;
127 
128 	char str_table[1]; /* contains all the strings */
129 };
130 
131 /* real size of the structure */
132 #define NAPTR_RDATA_SIZE(s) (sizeof(struct naptr_rdata) \
133 								+ (s).flags_len \
134 								+ (s).services_len \
135 								+ (s).regexp_len \
136 								+ (s).repl_len + 1 - 1)
137 
138 
139 /* A rec. struct */
140 struct a_rdata {
141 	unsigned char ip[4];
142 };
143 
144 struct aaaa_rdata {
145 	unsigned char ip6[16];
146 };
147 
148 /* cname rec. struct*/
149 struct cname_rdata {
150 	unsigned char name_len; /* name length w/o the terminating 0 */
151 	char name[1]; /* null terminated name (len=name_len+1) */
152 };
153 
154 /* real size of the structure */
155 #define CNAME_RDATA_SIZE(s) (sizeof(struct cname_rdata)+(s).name_len)
156 
157 /* dns character-string */
158 struct dns_cstr{
159 	char* cstr; /* pointer to null term. string */
160 	unsigned char cstr_len;
161 };
162 
163 /* txt rec. struct */
164 struct txt_rdata {
165 	unsigned short cstr_no; /* number of strings */
166 	unsigned short tslen; /* total strings table len */
167 	struct dns_cstr txt[1]; /* at least 1 */
168 	/* all txt[*].cstr point inside a string table at the end of the struct.*/
169 };
170 
171 #define TXT_RDATA_SIZE(s) \
172 	(sizeof(struct txt_rdata)+((s).cstr_no-1)*sizeof(struct dns_cstr)+\
173 	 	(s).tslen)
174 
175 /* ebl rec. struct, see
176    http://tools.ietf.org/html/draft-ietf-enum-branch-location-record-03 */
177 struct ebl_rdata {
178 	char* separator; /* points inside str_table */
179 	char* apex;      /* point inside str_table */
180 	unsigned char separator_len; /* separator len w/o the terminating 0 */
181 	unsigned char apex_len;      /* apex len w/p the terminating 0 */
182 	unsigned char position;
183 	char str_table[1]; /* contains the 2 strings: separator and apex */
184 };
185 #define EBL_RDATA_SIZE(s) \
186 	(sizeof(struct ebl_rdata)-1+(s).separator_len+1+(s).apex_len+1)
187 
188 
189 struct ptr_rdata {
190 	unsigned char ptrdname_len; /* name length w/o the terminating 0 */
191 	char ptrdname[1]; /* null terminated name (len=name_len+1) */
192 };
193 /* real size of the structure */
194 #define PTR_RDATA_SIZE(s) (sizeof(struct ptr_rdata)-1+(s).ptrdname_len+1)
195 
196 
197 #ifdef HAVE_RESOLV_RES
198 int match_search_list(const struct __res_state* res, char* name);
199 #endif
200 struct rdata* get_record(char* name, int type, int flags);
201 void free_rdata_list(struct rdata* head);
202 
203 
204 
205 #define rev_resolvehost(ip)\
206 					gethostbyaddr((char*)(ip)->u.addr, (ip)->len, (ip)->af)
207 
208 
209 
210 #define HEX2I(c) \
211 	(	(((c)>='0') && ((c)<='9'))? (c)-'0' :  \
212 		(((c)>='A') && ((c)<='F'))? ((c)-'A')+10 : \
213 		(((c)>='a') && ((c)<='f'))? ((c)-'a')+10 : -1 )
214 
215 
216 int str2ipbuf(str* st, ip_addr_t* ipb);
217 int str2ip6buf(str* st, ip_addr_t* ipb);
218 int str2ipxbuf(str* st, ip_addr_t* ipb);
219 ip_addr_t* str2ip(str* st);
220 ip_addr_t* str2ip6(str* st);
221 ip_addr_t* str2ipx(str* st);
222 
223 struct hostent* _sip_resolvehost(str* name, unsigned short* port, char* proto);
224 
225 
226 
227 /* gethostbyname wrapper, handles ip/ipv6 automatically */
_resolvehost(char * name)228 static inline struct hostent* _resolvehost(char* name)
229 {
230 	static struct hostent* he=0;
231 #ifdef HAVE_GETIPNODEBYNAME
232 	int err;
233 	static struct hostent* he2=0;
234 #endif
235 #ifndef DNS_IP_HACK
236 	int len;
237 #endif
238 #ifdef DNS_IP_HACK
239 	struct ip_addr* ip;
240 	str s;
241 
242 	s.s = (char*)name;
243 	s.len = strlen(name);
244 
245 	/* check if it's an ip address */
246 	if ( ((ip=str2ip(&s))!=0)
247 		  || ((ip=str2ip6(&s))!=0)
248 		){
249 		/* we are lucky, this is an ip address */
250 		return ip_addr2he(&s, ip);
251 	}
252 
253 #else /* DNS_IP_HACK */
254 	len=0;
255 	if (*name=='['){
256 		len=strlen(name);
257 		if (len && (name[len-1]==']')){
258 			name[len-1]=0; /* remove '[' */
259 			name++; /* skip '[' */
260 			goto skip_ipv4;
261 		}
262 	}
263 #endif
264 	/* ipv4 */
265 	he=dns_func.sr_gethostbyname(name);
266 
267 	if(he==0 && cfg_get(core, core_cfg, dns_try_ipv6)){
268 #ifndef DNS_IP_HACK
269 skip_ipv4:
270 #endif
271 		/*try ipv6*/
272 	#ifdef HAVE_GETHOSTBYNAME2
273 		he=dns_func.sr_gethostbyname2(name, AF_INET6);
274 	#elif defined HAVE_GETIPNODEBYNAME
275 		/* on solaris 8 getipnodebyname has a memory leak,
276 		 * after some time calls to it will fail with err=3
277 		 * solution: patch your solaris 8 installation */
278 		if (he2) freehostent(he2);
279 		he=he2=getipnodebyname(name, AF_INET6, 0, &err);
280 	#else
281 		#error neither gethostbyname2 or getipnodebyname present
282 	#endif
283 #ifndef DNS_IP_HACK
284 		if (len) name[len-2]=']'; /* restore */
285 #endif
286 	}
287 	return he;
288 }
289 
290 
291 int resolv_init(void);
292 
293 /* callback/fixup functions executed by the configuration framework */
294 void resolv_reinit(str *gname, str *name);
295 int dns_reinit_fixup(void *handle, str *gname, str *name, void **val);
296 int dns_try_ipv6_fixup(void *handle, str *gname, str *name, void **val);
297 void reinit_proto_prefs(str *gname, str *name);
298 
299 struct dns_srv_proto {
300 	char proto;
301 	int proto_pref;
302 };
303 void create_srv_name(char proto, str *name, char *srv);
304 size_t create_srv_pref_list(char *proto, struct dns_srv_proto *list);
305 
306 #ifdef DNS_WATCHDOG_SUPPORT
307 /* callback function that is called by the child processes
308  * when they reinitialize the resolver
309  *
310  * Note, that this callback is called by each chiled process separately!!!
311  * If the callback is registered after forking, only the child process
312  * that installs the hook will call the callback.
313  */
314 typedef void (*on_resolv_reinit)(str*);
315 int register_resolv_reinit_cb(on_resolv_reinit cb);
316 #endif
317 
318 
319 int sip_hostport2su(union sockaddr_union* su, str* host, unsigned short port,
320 						char* proto);
321 
322 
323 
324 /* wrappers */
325 #ifdef USE_DNS_CACHE
326 #define resolvehost dns_resolvehost
327 #define sip_resolvehost dns_sip_resolvehost
328 #else
329 #define resolvehost _resolvehost
330 #define sip_resolvehost _sip_resolvehost
331 #endif
332 
333 
334 
335 #ifdef USE_NAPTR
336 /* NAPTR helper functions */
337 typedef unsigned int naptr_bmp_t; /* type used for keeping track of tried
338 									 naptr records*/
339 #define MAX_NAPTR_RRS (sizeof(naptr_bmp_t)*8)
340 
341 /* use before first call to naptr_sip_iterate */
342 #define naptr_iterate_init(bmp) \
343 	do{ \
344 		*(bmp)=0; \
345 	}while(0) \
346 
347 struct rdata* naptr_sip_iterate(struct rdata* naptr_head,
348 										naptr_bmp_t* tried,
349 										str* srv_name, char* proto);
350 /* returns sip proto if valis sip naptr record, .-1 otherwise */
351 char naptr_get_sip_proto(struct naptr_rdata* n);
352 /* returns true if new_proto is preferred over old_proto */
353 int naptr_proto_preferred(char new_proto, char old_proto);
354 /* returns true if we support the protocol */
355 int naptr_proto_supported(char proto);
356 /* choose between 2 naptr records, should take into account local
357  * preferences too
358  * returns 1 if the new record was selected, 0 otherwise */
359 int naptr_choose (struct naptr_rdata** crt, char* crt_proto,
360 									struct naptr_rdata* n , char n_proto);
361 
362 #endif/* USE_NAPTR */
363 
364 struct hostent* no_naptr_srv_sip_resolvehost(str* name, unsigned short* port,
365 		char* proto);
366 
367 #endif
368