kamailio.cfg: removed sample db_mode parameter for domain module
[sip-router] / resolve.h
1 /*
2  * $Id$
3  *
4  * resolver related functions
5  *
6  * Copyright (C) 2001-2003 FhG Fokus
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  *  2003-04-12  support for resolving ipv6 address references added (andrei)
32  *  2004-07-28  darwin needs nameser_compat.h (andrei)
33  *  2006-07-13  rdata structures put on diet (andrei)
34  *  2006-07-17  rdata contains now also the record name (andrei)
35  *  2006-08-18  get_record uses flags (andrei)
36  *  2006-06-16  naptr support (andrei)
37  */
38
39
40
41 #ifndef __resolve_h
42 #define __resolve_h
43
44 #include <sys/types.h>
45 #include <sys/socket.h>
46 #include <netinet/in.h>
47 #include <netdb.h>
48 #include <arpa/nameser.h>
49 #include <resolv.h>
50 #include "counters.h"
51
52 #ifdef __OS_darwin
53 #include <arpa/nameser_compat.h>
54 #endif
55
56 #include "ip_addr.h"
57 #ifdef USE_DNS_CACHE
58 #include "dns_wrappers.h"
59 #endif
60
61 /* define RESOLVE_DBG for debugging info (very noisy) */
62 #define RESOLVE_DBG
63 /* define NAPTR_DBG for naptr related debugging info (very noisy) */
64 #define NAPTR_DBG
65
66
67 #define MAX_QUERY_SIZE 8192
68 #define ANS_SIZE       8192
69 #define DNS_HDR_SIZE     12
70 #define MAX_DNS_NAME 256
71 #define MAX_DNS_STRING 255
72
73 #ifndef T_EBL
74 /** not official yet - iEnum. */
75 #define T_EBL 65300
76 #endif
77
78 /* get_record flags */
79 #define RES_ONLY_TYPE 1   /* return only the specified type records */
80 #define RES_AR            2   /* return also the additional records */
81
82 /* counter for failed DNS requests
83 */
84 struct dns_counters_h {
85     counter_handle_t failed_dns_req;
86 };
87
88 extern struct dns_counters_h dns_cnts_h;
89
90 /* query union*/
91 union dns_query{
92         HEADER hdr;
93         unsigned char buff[MAX_QUERY_SIZE];
94 };
95
96
97 /* rdata struct*/
98 struct rdata {
99         unsigned short type;
100         unsigned short pclass;
101         unsigned int   ttl;
102         void* rdata;
103         struct rdata* next;
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 /* real size of the structure */
108 #define RDATA_SIZE(s) (sizeof(struct rdata)+(s).name_len) /* +1-1 */
109
110
111 /* srv rec. struct*/
112 struct srv_rdata {
113         unsigned short priority;
114         unsigned short weight;
115         unsigned short port;
116         unsigned char name_len; /* name length w/o the terminating 0 */
117         char name[1]; /* null terminated name (len=name_len+1) */
118 };
119
120
121 /* real size of the structure */
122 #define SRV_RDATA_SIZE(s) (sizeof(struct srv_rdata)+(s).name_len)
123
124 /* naptr rec. struct*/
125 struct naptr_rdata {
126         char* flags;    /* points inside str_table */
127         char* services; /* points inside str_table */
128         char* regexp;   /* points inside str_table */
129         char* repl;     /* points inside str_table, null terminated */
130         
131         unsigned short order;
132         unsigned short pref;
133         
134         unsigned char flags_len;
135         unsigned char services_len;
136         unsigned char regexp_len;
137         unsigned char repl_len; /* not currently used */
138         
139         char str_table[1]; /* contains all the strings */
140 };
141
142 /* real size of the structure */
143 #define NAPTR_RDATA_SIZE(s) (sizeof(struct naptr_rdata) \
144                                                                 + (s).flags_len \
145                                                                 + (s).services_len \
146                                                                 + (s).regexp_len \
147                                                                 + (s).repl_len + 1 - 1)
148
149
150 /* A rec. struct */
151 struct a_rdata {
152         unsigned char ip[4];
153 };
154
155 struct aaaa_rdata {
156         unsigned char ip6[16];
157 };
158
159 /* cname rec. struct*/
160 struct cname_rdata {
161         unsigned char name_len; /* name length w/o the terminating 0 */
162         char name[1]; /* null terminated name (len=name_len+1) */
163 };
164
165 /* real size of the structure */
166 #define CNAME_RDATA_SIZE(s) (sizeof(struct cname_rdata)+(s).name_len)
167
168 /* dns character-string */
169 struct dns_cstr{
170         char* cstr; /* pointer to null term. string */
171         unsigned char cstr_len;
172 };
173
174 /* txt rec. struct */
175 struct txt_rdata {
176         unsigned short cstr_no; /* number of strings */
177         unsigned short tslen; /* total strings table len */
178         struct dns_cstr txt[1]; /* at least 1 */
179         /* all txt[*].cstr point inside a string table at the end of the struct.*/
180 };
181
182 #define TXT_RDATA_SIZE(s) \
183         (sizeof(struct txt_rdata)+((s).cstr_no-1)*sizeof(struct dns_cstr)+\
184                 (s).tslen)
185
186 /* ebl rec. struct, see
187    http://tools.ietf.org/html/draft-ietf-enum-branch-location-record-03 */
188 struct ebl_rdata {
189         char* separator; /* points inside str_table */
190         char* apex;      /* point inside str_table */
191         unsigned char separator_len; /* separator len w/o the terminating 0 */
192         unsigned char apex_len;      /* apex len w/p the terminating 0 */
193         unsigned char position;
194         char str_table[1]; /* contains the 2 strings: separator and apex */
195 };
196 #define EBL_RDATA_SIZE(s) \
197         (sizeof(struct ebl_rdata)-1+(s).separator_len+1+(s).apex_len+1)
198
199
200 struct ptr_rdata {
201         unsigned char ptrdname_len; /* name length w/o the terminating 0 */
202         char ptrdname[1]; /* null terminated name (len=name_len+1) */
203 };
204 /* real size of the structure */
205 #define PTR_RDATA_SIZE(s) (sizeof(struct ptr_rdata)-1+(s).ptrdname_len+1)
206
207
208 #ifdef HAVE_RESOLV_RES
209 int match_search_list(const struct __res_state* res, char* name);
210 #endif
211 struct rdata* get_record(char* name, int type, int flags);
212 void free_rdata_list(struct rdata* head);
213
214
215
216 #define rev_resolvehost(ip)\
217                                         gethostbyaddr((char*)(ip)->u.addr, (ip)->len, (ip)->af)
218
219
220
221 #define HEX2I(c) \
222         (       (((c)>='0') && ((c)<='9'))? (c)-'0' :  \
223                 (((c)>='A') && ((c)<='F'))? ((c)-'A')+10 : \
224                 (((c)>='a') && ((c)<='f'))? ((c)-'a')+10 : -1 )
225
226
227
228
229
230 /* converts a str to an ipv4 address, returns the address or 0 on error
231    Warning: the result is a pointer to a statically allocated structure */
232 static inline struct ip_addr* str2ip(str* st)
233 {
234         int i;
235         unsigned char *limit;
236         static struct ip_addr ip;
237         unsigned char* s;
238
239         s=(unsigned char*)st->s;
240
241         /*init*/
242         ip.u.addr32[0]=0;
243         i=0;
244         limit=(unsigned char*)(st->s + st->len);
245
246         for(;s<limit ;s++){
247                 if (*s=='.'){
248                                 i++;
249                                 if (i>3) goto error_dots;
250                 }else if ( (*s <= '9' ) && (*s >= '0') ){
251                                 ip.u.addr[i]=ip.u.addr[i]*10+*s-'0';
252                 }else{
253                                 //error unknown char
254                                 goto error_char;
255                 }
256         }
257         if (i<3) goto error_dots;
258         ip.af=AF_INET;
259         ip.len=4;
260         
261         return &ip;
262 error_dots:
263 #ifdef RESOLVE_DBG
264         DBG("str2ip: ERROR: too %s dots in [%.*s]\n", (i>3)?"many":"few", 
265                         st->len, st->s);
266 #endif
267         return 0;
268  error_char:
269         /*
270         DBG("str2ip: WARNING: unexpected char %c in [%.*s]\n", *s, st->len, st->s);
271         */
272         return 0;
273 }
274
275
276 #ifdef USE_IPV6
277 /* returns an ip_addr struct.; on error returns 0
278  * the ip_addr struct is static, so subsequent calls will destroy its content*/
279 static inline struct ip_addr* str2ip6(str* st)
280 {
281         int i, idx1, rest;
282         int no_colons;
283         int double_colon;
284         int hex;
285         static struct ip_addr ip;
286         unsigned short* addr_start;
287         unsigned short addr_end[8];
288         unsigned short* addr;
289         unsigned char* limit;
290         unsigned char* s;
291         
292         /* init */
293         if ((st->len) && (st->s[0]=='[')){
294                 /* skip over [ ] */
295                 if (st->s[st->len-1]!=']') goto error_char;
296                 s=(unsigned char*)(st->s+1);
297                 limit=(unsigned char*)(st->s+st->len-1);
298         }else{
299                 s=(unsigned char*)st->s;
300                 limit=(unsigned char*)(st->s+st->len);
301         }
302         i=idx1=rest=0;
303         double_colon=0;
304         no_colons=0;
305         ip.af=AF_INET6;
306         ip.len=16;
307         addr_start=ip.u.addr16;
308         addr=addr_start;
309         memset(addr_start, 0 , 8*sizeof(unsigned short));
310         memset(addr_end, 0 , 8*sizeof(unsigned short));
311         for (; s<limit; s++){
312                 if (*s==':'){
313                         no_colons++;
314                         if (no_colons>7) goto error_too_many_colons;
315                         if (double_colon){
316                                 idx1=i;
317                                 i=0;
318                                 if (addr==addr_end) goto error_colons;
319                                 addr=addr_end;
320                         }else{
321                                 double_colon=1;
322                                 addr[i]=htons(addr[i]);
323                                 i++;
324                         }
325                 }else if ((hex=HEX2I(*s))>=0){
326                                 addr[i]=addr[i]*16+hex;
327                                 double_colon=0;
328                 }else{
329                         /* error, unknown char */
330                         goto error_char;
331                 }
332         }
333         if (!double_colon){ /* not ending in ':' */
334                 addr[i]=htons(addr[i]);
335                 i++; 
336         }
337         /* if address contained '::' fix it */
338         if (addr==addr_end){
339                 rest=8-i-idx1;
340                 memcpy(addr_start+idx1+rest, addr_end, i*sizeof(unsigned short));
341         }else{
342                 /* no double colons inside */
343                 if (no_colons<7) goto error_too_few_colons;
344         }
345 /*
346         DBG("str2ip6: idx1=%d, rest=%d, no_colons=%d, hex=%x\n",
347                         idx1, rest, no_colons, hex);
348         DBG("str2ip6: address %x:%x:%x:%x:%x:%x:%x:%x\n", 
349                         addr_start[0], addr_start[1], addr_start[2],
350                         addr_start[3], addr_start[4], addr_start[5],
351                         addr_start[6], addr_start[7] );
352 */
353         return &ip;
354
355 error_too_many_colons:
356 #ifdef RESOLVE_DBG
357         DBG("str2ip6: ERROR: too many colons in [%.*s]\n", st->len, st->s);
358 #endif
359         return 0;
360
361 error_too_few_colons:
362 #ifdef RESOLVE_DBG
363         DBG("str2ip6: ERROR: too few colons in [%.*s]\n", st->len, st->s);
364 #endif
365         return 0;
366
367 error_colons:
368 #ifdef RESOLVE_DBG
369         DBG("str2ip6: ERROR: too many double colons in [%.*s]\n", st->len, st->s);
370 #endif
371         return 0;
372
373 error_char:
374         /*
375         DBG("str2ip6: WARNING: unexpected char %c in  [%.*s]\n", *s, st->len,
376                         st->s);*/
377         return 0;
378 }
379 #endif /* USE_IPV6 */
380
381
382
383 struct hostent* _sip_resolvehost(str* name, unsigned short* port, char* proto);
384
385
386
387 /* gethostbyname wrapper, handles ip/ipv6 automatically */
388 static inline struct hostent* _resolvehost(char* name)
389 {
390         static struct hostent* he=0;
391 #ifdef HAVE_GETIPNODEBYNAME 
392 #ifdef USE_IPV6
393         int err;
394         static struct hostent* he2=0;
395 #endif
396 #endif
397 #ifndef DNS_IP_HACK
398 #ifdef USE_IPV6
399         int len;
400 #endif
401 #endif
402 #ifdef DNS_IP_HACK
403         struct ip_addr* ip;
404         str s;
405
406         s.s = (char*)name;
407         s.len = strlen(name);
408
409         /* check if it's an ip address */
410         if ( ((ip=str2ip(&s))!=0)
411 #ifdef  USE_IPV6
412                   || ((ip=str2ip6(&s))!=0)
413 #endif
414                 ){
415                 /* we are lucky, this is an ip address */
416                 return ip_addr2he(&s, ip);
417         }
418         
419 #else /* DNS_IP_HACK */
420 #ifdef USE_IPV6
421         len=0;
422         if (*name=='['){
423                 len=strlen(name);
424                 if (len && (name[len-1]==']')){
425                         name[len-1]=0; /* remove '[' */
426                         name++; /* skip '[' */
427                         goto skip_ipv4;
428                 }
429         }
430 #endif
431 #endif
432         /* ipv4 */
433         he=gethostbyname(name);
434 #ifdef USE_IPV6
435         if(he==0 && cfg_get(core, core_cfg, dns_try_ipv6)){
436 #ifndef DNS_IP_HACK
437 skip_ipv4:
438 #endif
439                 /*try ipv6*/
440         #ifdef HAVE_GETHOSTBYNAME2
441                 he=gethostbyname2(name, AF_INET6);
442         #elif defined HAVE_GETIPNODEBYNAME
443                 /* on solaris 8 getipnodebyname has a memory leak,
444                  * after some time calls to it will fail with err=3
445                  * solution: patch your solaris 8 installation */
446                 if (he2) freehostent(he2);
447                 he=he2=getipnodebyname(name, AF_INET6, 0, &err);
448         #else
449                 #error neither gethostbyname2 or getipnodebyname present
450         #endif
451 #ifndef DNS_IP_HACK
452                 if (len) name[len-2]=']'; /* restore */
453 #endif
454         }
455 #endif
456         return he;
457 }
458
459
460 int resolv_init(void);
461
462 /* callback/fixup functions executed by the configuration framework */
463 void resolv_reinit(str *gname, str *name);
464 int dns_reinit_fixup(void *handle, str *gname, str *name, void **val);
465 int dns_try_ipv6_fixup(void *handle, str *gname, str *name, void **val);
466 void reinit_naptr_proto_prefs(str *gname, str *name);
467
468 #ifdef DNS_WATCHDOG_SUPPORT
469 /* callback function that is called by the child processes
470  * when they reinitialize the resolver
471  *
472  * Note, that this callback is called by each chiled process separately!!!
473  * If the callback is registered after forking, only the child process
474  * that installs the hook will call the callback.
475  */
476 typedef void (*on_resolv_reinit)(str*);
477 int register_resolv_reinit_cb(on_resolv_reinit cb);
478 #endif
479
480
481 int sip_hostport2su(union sockaddr_union* su, str* host, unsigned short port,
482                                                 char* proto);
483
484
485
486 /* wrappers */
487 #ifdef USE_DNS_CACHE
488 #define resolvehost dns_resolvehost
489 #define sip_resolvehost dns_sip_resolvehost
490 #else
491 #define resolvehost _resolvehost
492 #define sip_resolvehost _sip_resolvehost
493 #endif
494
495
496
497 #ifdef USE_NAPTR
498 /* NAPTR helper functions */
499 typedef unsigned int naptr_bmp_t; /* type used for keeping track of tried
500                                                                          naptr records*/
501 #define MAX_NAPTR_RRS (sizeof(naptr_bmp_t)*8)
502
503 /* use before first call to naptr_sip_iterate */
504 #define naptr_iterate_init(bmp) \
505         do{ \
506                 *(bmp)=0; \
507         }while(0) \
508
509 struct rdata* naptr_sip_iterate(struct rdata* naptr_head, 
510                                                                                 naptr_bmp_t* tried,
511                                                                                 str* srv_name, char* proto);
512 /* returns sip proto if valis sip naptr record, .-1 otherwise */
513 char naptr_get_sip_proto(struct naptr_rdata* n);
514 /* returns true if new_proto is preferred over old_proto */
515 int naptr_proto_preferred(char new_proto, char old_proto);
516 /* returns true if we support the protocol */
517 int naptr_proto_supported(char proto);
518 /* choose between 2 naptr records, should take into account local
519  * preferences too
520  * returns 1 if the new record was selected, 0 otherwise */
521 int naptr_choose (struct naptr_rdata** crt, char* crt_proto,
522                                                                         struct naptr_rdata* n , char n_proto);
523
524 #endif/* USE_NAPTR */
525
526 #endif