resolve.h 13 KB

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