• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Data Structures
  • Files
  • Directories
  • File List
  • Globals

resolve.h

00001 /*
00002  * $Id$
00003  *
00004  * resolver related functions
00005  *
00006  * Copyright (C) 2001-2003 FhG Fokus
00007  *
00008  * This file is part of ser, a free SIP server.
00009  *
00010  * ser is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version
00014  *
00015  * For a license to use the ser software under conditions
00016  * other than those described here, or to purchase support for this
00017  * software, please contact iptel.org by e-mail at the following addresses:
00018  *    info@iptel.org
00019  *
00020  * ser is distributed in the hope that it will be useful,
00021  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00022  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023  * GNU General Public License for more details.
00024  *
00025  * You should have received a copy of the GNU General Public License 
00026  * along with this program; if not, write to the Free Software 
00027  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00028  */
00029 /* History:
00030  * --------
00031  *  2003-04-12  support for resolving ipv6 address references added (andrei)
00032  *  2004-07-28  darwin needs nameser_compat.h (andrei)
00033  *  2006-07-13  rdata structures put on diet (andrei)
00034  *  2006-07-17  rdata contains now also the record name (andrei)
00035  *  2006-08-18  get_record uses flags (andrei)
00036  *  2006-06-16  naptr support (andrei)
00037  */
00038 
00039 
00040 
00041 #ifndef __resolve_h
00042 #define __resolve_h
00043 
00044 #include <sys/types.h>
00045 #include <sys/socket.h>
00046 #include <netinet/in.h>
00047 #include <netdb.h>
00048 #include <arpa/nameser.h>
00049 #include <resolv.h>
00050 #include "counters.h"
00051 
00052 #ifdef __OS_darwin
00053 #include <arpa/nameser_compat.h>
00054 #endif
00055 
00056 #include "ip_addr.h"
00057 #ifdef USE_DNS_CACHE
00058 #include "dns_wrappers.h"
00059 #endif
00060 
00061 /* define RESOLVE_DBG for debugging info (very noisy) */
00062 #define RESOLVE_DBG
00063 /* define NAPTR_DBG for naptr related debugging info (very noisy) */
00064 #define NAPTR_DBG
00065 
00066 
00067 #define MAX_QUERY_SIZE 8192
00068 #define ANS_SIZE       8192
00069 #define DNS_HDR_SIZE     12
00070 #define MAX_DNS_NAME 256
00071 #define MAX_DNS_STRING 255
00072 
00073 #ifndef T_EBL
00074 
00075 #define T_EBL 65300
00076 #endif
00077 
00078 /* get_record flags */
00079 #define RES_ONLY_TYPE 1   /* return only the specified type records */
00080 #define RES_AR            2   /* return also the additional records */
00081 
00082 /* counter for failed DNS requests
00083 */
00084 struct dns_counters_h {
00085     counter_handle_t failed_dns_req;
00086 };
00087 
00088 extern struct dns_counters_h dns_cnts_h;
00089 
00090 /* query union*/
00091 union dns_query{
00092         HEADER hdr;
00093         unsigned char buff[MAX_QUERY_SIZE];
00094 };
00095 
00096 
00097 /* rdata struct*/
00098 struct rdata {
00099         unsigned short type;
00100         unsigned short pclass;
00101         unsigned int   ttl;
00102         void* rdata;
00103         struct rdata* next;
00104         unsigned char name_len; /* name length w/o the terminating 0 */
00105         char name[1]; /* null terminated name (len=name_len+1) */
00106 };
00107 /* real size of the structure */
00108 #define RDATA_SIZE(s) (sizeof(struct rdata)+(s).name_len) /* +1-1 */
00109 
00110 
00111 /* srv rec. struct*/
00112 struct srv_rdata {
00113         unsigned short priority;
00114         unsigned short weight;
00115         unsigned short port;
00116         unsigned char name_len; /* name length w/o the terminating 0 */
00117         char name[1]; /* null terminated name (len=name_len+1) */
00118 };
00119 
00120 
00121 /* real size of the structure */
00122 #define SRV_RDATA_SIZE(s) (sizeof(struct srv_rdata)+(s).name_len)
00123 
00124 /* naptr rec. struct*/
00125 struct naptr_rdata {
00126         char* flags;    /* points inside str_table */
00127         char* services; /* points inside str_table */
00128         char* regexp;   /* points inside str_table */
00129         char* repl;     /* points inside str_table, null terminated */
00130         
00131         unsigned short order;
00132         unsigned short pref;
00133         
00134         unsigned char flags_len;
00135         unsigned char services_len;
00136         unsigned char regexp_len;
00137         unsigned char repl_len; /* not currently used */
00138         
00139         char str_table[1]; /* contains all the strings */
00140 };
00141 
00142 /* real size of the structure */
00143 #define NAPTR_RDATA_SIZE(s) (sizeof(struct naptr_rdata) \
00144                                                                 + (s).flags_len \
00145                                                                 + (s).services_len \
00146                                                                 + (s).regexp_len \
00147                                                                 + (s).repl_len + 1 - 1)
00148 
00149 
00150 /* A rec. struct */
00151 struct a_rdata {
00152         unsigned char ip[4];
00153 };
00154 
00155 struct aaaa_rdata {
00156         unsigned char ip6[16];
00157 };
00158 
00159 /* cname rec. struct*/
00160 struct cname_rdata {
00161         unsigned char name_len; /* name length w/o the terminating 0 */
00162         char name[1]; /* null terminated name (len=name_len+1) */
00163 };
00164 
00165 /* real size of the structure */
00166 #define CNAME_RDATA_SIZE(s) (sizeof(struct cname_rdata)+(s).name_len)
00167 
00168 /* dns character-string */
00169 struct dns_cstr{
00170         char* cstr; /* pointer to null term. string */
00171         unsigned char cstr_len;
00172 };
00173 
00174 /* txt rec. struct */
00175 struct txt_rdata {
00176         unsigned short cstr_no; /* number of strings */
00177         unsigned short tslen; /* total strings table len */
00178         struct dns_cstr txt[1]; /* at least 1 */
00179         /* all txt[*].cstr point inside a string table at the end of the struct.*/
00180 };
00181 
00182 #define TXT_RDATA_SIZE(s) \
00183         (sizeof(struct txt_rdata)+((s).cstr_no-1)*sizeof(struct dns_cstr)+\
00184                 (s).tslen)
00185 
00186 /* ebl rec. struct, see
00187    http://tools.ietf.org/html/draft-ietf-enum-branch-location-record-03 */
00188 struct ebl_rdata {
00189         char* separator; /* points inside str_table */
00190         char* apex;      /* point inside str_table */
00191         unsigned char separator_len; /* separator len w/o the terminating 0 */
00192         unsigned char apex_len;      /* apex len w/p the terminating 0 */
00193         unsigned char position;
00194         char str_table[1]; /* contains the 2 strings: separator and apex */
00195 };
00196 #define EBL_RDATA_SIZE(s) \
00197         (sizeof(struct ebl_rdata)-1+(s).separator_len+1+(s).apex_len+1)
00198 
00199 
00200 struct ptr_rdata {
00201         unsigned char ptrdname_len; /* name length w/o the terminating 0 */
00202         char ptrdname[1]; /* null terminated name (len=name_len+1) */
00203 };
00204 /* real size of the structure */
00205 #define PTR_RDATA_SIZE(s) (sizeof(struct ptr_rdata)-1+(s).ptrdname_len+1)
00206 
00207 
00208 #ifdef HAVE_RESOLV_RES
00209 int match_search_list(const struct __res_state* res, char* name);
00210 #endif
00211 struct rdata* get_record(char* name, int type, int flags);
00212 void free_rdata_list(struct rdata* head);
00213 
00214 
00215 
00216 #define rev_resolvehost(ip)\
00217                                         gethostbyaddr((char*)(ip)->u.addr, (ip)->len, (ip)->af)
00218 
00219 
00220 
00221 #define HEX2I(c) \
00222         (       (((c)>='0') && ((c)<='9'))? (c)-'0' :  \
00223                 (((c)>='A') && ((c)<='F'))? ((c)-'A')+10 : \
00224                 (((c)>='a') && ((c)<='f'))? ((c)-'a')+10 : -1 )
00225 
00226 
00227 
00228 
00229 
00230 /* converts a str to an ipv4 address, returns the address or 0 on error
00231    Warning: the result is a pointer to a statically allocated structure */
00232 static inline struct ip_addr* str2ip(str* st)
00233 {
00234         int i;
00235         unsigned char *limit;
00236         static struct ip_addr ip;
00237         unsigned char* s;
00238 
00239         s=(unsigned char*)st->s;
00240 
00241         /*init*/
00242         ip.u.addr32[0]=0;
00243         i=0;
00244         limit=(unsigned char*)(st->s + st->len);
00245 
00246         for(;s<limit ;s++){
00247                 if (*s=='.'){
00248                                 i++;
00249                                 if (i>3) goto error_dots;
00250                 }else if ( (*s <= '9' ) && (*s >= '0') ){
00251                                 ip.u.addr[i]=ip.u.addr[i]*10+*s-'0';
00252                 }else{
00253                                 //error unknown char
00254                                 goto error_char;
00255                 }
00256         }
00257         if (i<3) goto error_dots;
00258         ip.af=AF_INET;
00259         ip.len=4;
00260         
00261         return &ip;
00262 error_dots:
00263 #ifdef RESOLVE_DBG
00264         DBG("str2ip: ERROR: too %s dots in [%.*s]\n", (i>3)?"many":"few", 
00265                         st->len, st->s);
00266 #endif
00267         return 0;
00268  error_char:
00269         /*
00270         DBG("str2ip: WARNING: unexpected char %c in [%.*s]\n", *s, st->len, st->s);
00271         */
00272         return 0;
00273 }
00274 
00275 
00276 #ifdef USE_IPV6
00277 /* returns an ip_addr struct.; on error returns 0
00278  * the ip_addr struct is static, so subsequent calls will destroy its content*/
00279 static inline struct ip_addr* str2ip6(str* st)
00280 {
00281         int i, idx1, rest;
00282         int no_colons;
00283         int double_colon;
00284         int hex;
00285         static struct ip_addr ip;
00286         unsigned short* addr_start;
00287         unsigned short addr_end[8];
00288         unsigned short* addr;
00289         unsigned char* limit;
00290         unsigned char* s;
00291         
00292         /* init */
00293         if ((st->len) && (st->s[0]=='[')){
00294                 /* skip over [ ] */
00295                 if (st->s[st->len-1]!=']') goto error_char;
00296                 s=(unsigned char*)(st->s+1);
00297                 limit=(unsigned char*)(st->s+st->len-1);
00298         }else{
00299                 s=(unsigned char*)st->s;
00300                 limit=(unsigned char*)(st->s+st->len);
00301         }
00302         i=idx1=rest=0;
00303         double_colon=0;
00304         no_colons=0;
00305         ip.af=AF_INET6;
00306         ip.len=16;
00307         addr_start=ip.u.addr16;
00308         addr=addr_start;
00309         memset(addr_start, 0 , 8*sizeof(unsigned short));
00310         memset(addr_end, 0 , 8*sizeof(unsigned short));
00311         for (; s<limit; s++){
00312                 if (*s==':'){
00313                         no_colons++;
00314                         if (no_colons>7) goto error_too_many_colons;
00315                         if (double_colon){
00316                                 idx1=i;
00317                                 i=0;
00318                                 if (addr==addr_end) goto error_colons;
00319                                 addr=addr_end;
00320                         }else{
00321                                 double_colon=1;
00322                                 addr[i]=htons(addr[i]);
00323                                 i++;
00324                         }
00325                 }else if ((hex=HEX2I(*s))>=0){
00326                                 addr[i]=addr[i]*16+hex;
00327                                 double_colon=0;
00328                 }else{
00329                         /* error, unknown char */
00330                         goto error_char;
00331                 }
00332         }
00333         if (!double_colon){ /* not ending in ':' */
00334                 addr[i]=htons(addr[i]);
00335                 i++; 
00336         }
00337         /* if address contained '::' fix it */
00338         if (addr==addr_end){
00339                 rest=8-i-idx1;
00340                 memcpy(addr_start+idx1+rest, addr_end, i*sizeof(unsigned short));
00341         }else{
00342                 /* no double colons inside */
00343                 if (no_colons<7) goto error_too_few_colons;
00344         }
00345 /*
00346         DBG("str2ip6: idx1=%d, rest=%d, no_colons=%d, hex=%x\n",
00347                         idx1, rest, no_colons, hex);
00348         DBG("str2ip6: address %x:%x:%x:%x:%x:%x:%x:%x\n", 
00349                         addr_start[0], addr_start[1], addr_start[2],
00350                         addr_start[3], addr_start[4], addr_start[5],
00351                         addr_start[6], addr_start[7] );
00352 */
00353         return &ip;
00354 
00355 error_too_many_colons:
00356 #ifdef RESOLVE_DBG
00357         DBG("str2ip6: ERROR: too many colons in [%.*s]\n", st->len, st->s);
00358 #endif
00359         return 0;
00360 
00361 error_too_few_colons:
00362 #ifdef RESOLVE_DBG
00363         DBG("str2ip6: ERROR: too few colons in [%.*s]\n", st->len, st->s);
00364 #endif
00365         return 0;
00366 
00367 error_colons:
00368 #ifdef RESOLVE_DBG
00369         DBG("str2ip6: ERROR: too many double colons in [%.*s]\n", st->len, st->s);
00370 #endif
00371         return 0;
00372 
00373 error_char:
00374         /*
00375         DBG("str2ip6: WARNING: unexpected char %c in  [%.*s]\n", *s, st->len,
00376                         st->s);*/
00377         return 0;
00378 }
00379 #endif /* USE_IPV6 */
00380 
00381 
00382 
00383 struct hostent* _sip_resolvehost(str* name, unsigned short* port, char* proto);
00384 
00385 
00386 
00387 /* gethostbyname wrapper, handles ip/ipv6 automatically */
00388 static inline struct hostent* _resolvehost(char* name)
00389 {
00390         static struct hostent* he=0;
00391 #ifdef HAVE_GETIPNODEBYNAME 
00392 #ifdef USE_IPV6
00393         int err;
00394         static struct hostent* he2=0;
00395 #endif
00396 #endif
00397 #ifndef DNS_IP_HACK
00398 #ifdef USE_IPV6
00399         int len;
00400 #endif
00401 #endif
00402 #ifdef DNS_IP_HACK
00403         struct ip_addr* ip;
00404         str s;
00405 
00406         s.s = (char*)name;
00407         s.len = strlen(name);
00408 
00409         /* check if it's an ip address */
00410         if ( ((ip=str2ip(&s))!=0)
00411 #ifdef  USE_IPV6
00412                   || ((ip=str2ip6(&s))!=0)
00413 #endif
00414                 ){
00415                 /* we are lucky, this is an ip address */
00416                 return ip_addr2he(&s, ip);
00417         }
00418         
00419 #else /* DNS_IP_HACK */
00420 #ifdef USE_IPV6
00421         len=0;
00422         if (*name=='['){
00423                 len=strlen(name);
00424                 if (len && (name[len-1]==']')){
00425                         name[len-1]=0; /* remove '[' */
00426                         name++; /* skip '[' */
00427                         goto skip_ipv4;
00428                 }
00429         }
00430 #endif
00431 #endif
00432         /* ipv4 */
00433         he=gethostbyname(name);
00434 #ifdef USE_IPV6
00435         if(he==0 && cfg_get(core, core_cfg, dns_try_ipv6)){
00436 #ifndef DNS_IP_HACK
00437 skip_ipv4:
00438 #endif
00439                 /*try ipv6*/
00440         #ifdef HAVE_GETHOSTBYNAME2
00441                 he=gethostbyname2(name, AF_INET6);
00442         #elif defined HAVE_GETIPNODEBYNAME
00443                 /* on solaris 8 getipnodebyname has a memory leak,
00444                  * after some time calls to it will fail with err=3
00445                  * solution: patch your solaris 8 installation */
00446                 if (he2) freehostent(he2);
00447                 he=he2=getipnodebyname(name, AF_INET6, 0, &err);
00448         #else
00449                 #error neither gethostbyname2 or getipnodebyname present
00450         #endif
00451 #ifndef DNS_IP_HACK
00452                 if (len) name[len-2]=']'; /* restore */
00453 #endif
00454         }
00455 #endif
00456         return he;
00457 }
00458 
00459 
00460 int resolv_init(void);
00461 
00462 /* callback/fixup functions executed by the configuration framework */
00463 void resolv_reinit(str *gname, str *name);
00464 int dns_reinit_fixup(void *handle, str *gname, str *name, void **val);
00465 int dns_try_ipv6_fixup(void *handle, str *gname, str *name, void **val);
00466 void reinit_naptr_proto_prefs(str *gname, str *name);
00467 
00468 #ifdef DNS_WATCHDOG_SUPPORT
00469 /* callback function that is called by the child processes
00470  * when they reinitialize the resolver
00471  *
00472  * Note, that this callback is called by each chiled process separately!!!
00473  * If the callback is registered after forking, only the child process
00474  * that installs the hook will call the callback.
00475  */
00476 typedef void (*on_resolv_reinit)(str*);
00477 int register_resolv_reinit_cb(on_resolv_reinit cb);
00478 #endif
00479 
00480 
00481 int sip_hostport2su(union sockaddr_union* su, str* host, unsigned short port,
00482                                                 char* proto);
00483 
00484 
00485 
00486 /* wrappers */
00487 #ifdef USE_DNS_CACHE
00488 #define resolvehost dns_resolvehost
00489 #define sip_resolvehost dns_sip_resolvehost
00490 #else
00491 #define resolvehost _resolvehost
00492 #define sip_resolvehost _sip_resolvehost
00493 #endif
00494 
00495 
00496 
00497 #ifdef USE_NAPTR
00498 /* NAPTR helper functions */
00499 typedef unsigned int naptr_bmp_t; /* type used for keeping track of tried
00500                                                                          naptr records*/
00501 #define MAX_NAPTR_RRS (sizeof(naptr_bmp_t)*8)
00502 
00503 /* use before first call to naptr_sip_iterate */
00504 #define naptr_iterate_init(bmp) \
00505         do{ \
00506                 *(bmp)=0; \
00507         }while(0) \
00508 
00509 struct rdata* naptr_sip_iterate(struct rdata* naptr_head, 
00510                                                                                 naptr_bmp_t* tried,
00511                                                                                 str* srv_name, char* proto);
00512 /* returns sip proto if valis sip naptr record, .-1 otherwise */
00513 char naptr_get_sip_proto(struct naptr_rdata* n);
00514 /* returns true if new_proto is preferred over old_proto */
00515 int naptr_proto_preferred(char new_proto, char old_proto);
00516 /* returns true if we support the protocol */
00517 int naptr_proto_supported(char proto);
00518 /* choose between 2 naptr records, should take into account local
00519  * preferences too
00520  * returns 1 if the new record was selected, 0 otherwise */
00521 int naptr_choose (struct naptr_rdata** crt, char* crt_proto,
00522                                                                         struct naptr_rdata* n , char n_proto);
00523 
00524 #endif/* USE_NAPTR */
00525 
00526 #endif

Generated on Tue May 22 2012 13:10:14 for SIP Router by  doxygen 1.7.1