resolve.h 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  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. #ifndef __resolve_h
  30. #define __resolve_h
  31. #include <sys/types.h>
  32. #include <sys/socket.h>
  33. #include <netdb.h>
  34. #include <arpa/nameser.h>
  35. #include "ip_addr.h"
  36. #define MAX_QUERY_SIZE 8192
  37. #define ANS_SIZE 8192
  38. #define DNS_HDR_SIZE 12
  39. #define MAX_DNS_NAME 256
  40. #define MAX_DNS_STRING 255
  41. /* query union*/
  42. union dns_query{
  43. HEADER hdr;
  44. unsigned char buff[MAX_QUERY_SIZE];
  45. };
  46. /* rdata struct*/
  47. struct rdata {
  48. unsigned short type;
  49. unsigned short class;
  50. unsigned int ttl;
  51. void* rdata;
  52. struct rdata* next;
  53. };
  54. /* srv rec. struct*/
  55. struct srv_rdata {
  56. unsigned short priority;
  57. unsigned short weight;
  58. unsigned short port;
  59. unsigned int name_len;
  60. char name[MAX_DNS_NAME];
  61. };
  62. /* naptr rec. struct*/
  63. struct naptr_rdata {
  64. unsigned short order;
  65. unsigned short pref;
  66. unsigned int flags_len;
  67. char flags[MAX_DNS_STRING];
  68. unsigned int services_len;
  69. char services[MAX_DNS_STRING];
  70. unsigned int regexp_len;
  71. char regexp[MAX_DNS_STRING];
  72. unsigned int repl_len; /* not currently used */
  73. char repl[MAX_DNS_NAME];
  74. };
  75. /* A rec. struct */
  76. struct a_rdata {
  77. unsigned char ip[4];
  78. };
  79. struct aaaa_rdata {
  80. unsigned char ip6[16];
  81. };
  82. /* cname rec. struct*/
  83. struct cname_rdata {
  84. char name[MAX_DNS_NAME];
  85. };
  86. struct rdata* get_record(char* name, int type);
  87. void free_rdata_list(struct rdata* head);
  88. #define rev_resolvehost(ip)\
  89. gethostbyaddr((char*)(ip)->u.addr, (ip)->len, (ip)->af);
  90. #define HEX2I(c) \
  91. ( (((c)>='0') && ((c)<='9'))? (c)-'0' : \
  92. (((c)>='A') && ((c)<='F'))? ((c)-'A')+10 : \
  93. (((c)>='a') && ((c)<='f'))? ((c)-'a')+10 : -1 )
  94. /* converts a str to an ipv4 address, returns the address or 0 on error
  95. Warning: the result is a pointer to a statically allocated structure */
  96. static inline struct ip_addr* str2ip(str* st)
  97. {
  98. int i;
  99. unsigned char *limit;
  100. static struct ip_addr ip;
  101. unsigned char* s;
  102. s = st->s;
  103. /*init*/
  104. ip.u.addr32[0]=0;
  105. i=0;
  106. limit=st->s + st->len;
  107. for(;s<limit ;s++){
  108. if (*s=='.'){
  109. i++;
  110. if (i>3) goto error_dots;
  111. }else if ( (*s <= '9' ) && (*s >= '0') ){
  112. ip.u.addr[i]=ip.u.addr[i]*10+*s-'0';
  113. }else{
  114. //error unknown char
  115. goto error_char;
  116. }
  117. }
  118. ip.af=AF_INET;
  119. ip.len=4;
  120. return &ip;
  121. /* FIXME: janakj - is this correct ?, we return always 0 here
  122. * Also we could use different loglevels here
  123. */
  124. error_dots:
  125. DBG("str2ip: ERROR: too many dots in [%.*s]\n", st->len, st->s);
  126. return 0;
  127. error_char:
  128. DBG("str2ip: WARNING: unexpected char %c in [%.*s]\n", *s, st->len, st->s);
  129. return 0;
  130. }
  131. /* returns an ip_addr struct.; on error returns 0
  132. * the ip_addr struct is static, so subsequent calls will destroy its content*/
  133. static inline struct ip_addr* str2ip6(str* st)
  134. {
  135. int i, idx1, rest;
  136. int no_colons;
  137. int double_colon;
  138. int hex;
  139. static struct ip_addr ip;
  140. unsigned short* addr_start;
  141. unsigned short addr_end[8];
  142. unsigned short* addr;
  143. unsigned char* limit;
  144. unsigned char* s;
  145. /* init */
  146. s=st->s;
  147. i=idx1=rest=0;
  148. double_colon=0;
  149. no_colons=0;
  150. ip.af=AF_INET6;
  151. ip.len=16;
  152. addr_start=ip.u.addr16;
  153. addr=addr_start;
  154. limit=st->s+st->len;
  155. memset(addr_start, 0 , 8*sizeof(unsigned short));
  156. memset(addr_end, 0 , 8*sizeof(unsigned short));
  157. for (; s<limit; s++){
  158. if (*s==':'){
  159. no_colons++;
  160. if (no_colons>7) goto error_too_many_colons;
  161. if (double_colon){
  162. idx1=i;
  163. i=0;
  164. if (addr==addr_end) goto error_colons;
  165. addr=addr_end;
  166. }else{
  167. double_colon=1;
  168. addr[i]=htons(addr[i]);
  169. i++;
  170. }
  171. }else if ((hex=HEX2I(*s))>=0){
  172. addr[i]=addr[i]*16+hex;
  173. double_colon=0;
  174. }else{
  175. /* error, unknown char */
  176. goto error_char;
  177. }
  178. }
  179. if (no_colons<2) goto error_too_few_colons;
  180. if (!double_colon){ /* not ending in ':' */
  181. addr[i]=htons(addr[i]);
  182. i++;
  183. }
  184. /* if address contained '::' fix it */
  185. if (addr==addr_end){
  186. rest=8-i-idx1;
  187. memcpy(addr_start+idx1+rest, addr_end, i*sizeof(unsigned short));
  188. }
  189. /*
  190. DBG("str2ip6: idx1=%d, rest=%d, no_colons=%d, hex=%x\n",
  191. idx1, rest, no_colons, hex);
  192. DBG("str2ip6: address %x:%x:%x:%x:%x:%x:%x:%x\n",
  193. addr_start[0], addr_start[1], addr_start[2],
  194. addr_start[3], addr_start[4], addr_start[5],
  195. addr_start[6], addr_start[7] );
  196. */
  197. return &ip;
  198. error_too_many_colons:
  199. DBG("str2ip6: ERROR: too many colons in [%.*s]\n", st->len, st->s);
  200. return 0;
  201. error_too_few_colons:
  202. DBG("str2ip6: ERROR: too few colons in [%.*s]\n", st->len, st->s);
  203. return 0;
  204. error_colons:
  205. DBG("str2ip6: ERROR: too many double colons in [%.*s]\n", st->len, st->s);
  206. return 0;
  207. error_char:
  208. DBG("str2ip6: WARNING: unexpected char %c in [%.*s]\n", *s, st->len,
  209. st->s);
  210. return 0;
  211. }
  212. struct hostent* sip_resolvehost(str* name, unsigned short* port);
  213. /* gethostbyname wrappers
  214. * use this, someday they will use a local cache */
  215. static inline struct hostent* resolvehost(const char* name)
  216. {
  217. static struct hostent* he=0;
  218. #ifdef HAVE_GETIPNODEBYNAME
  219. int err;
  220. static struct hostent* he2=0;
  221. #endif
  222. #ifdef DNS_IP_HACK
  223. struct ip_addr* ip;
  224. str s;
  225. s.s = (char*)name;
  226. s.len = strlen(name);
  227. /* check if it's an ip address */
  228. if ( ((ip=str2ip(&s))!=0)
  229. #ifdef USE_IPV6
  230. || ((ip=str2ip6(&s))!=0)
  231. #endif
  232. ){
  233. /* we are lucky, this is an ip address */
  234. return ip_addr2he(&s, ip);
  235. }
  236. #endif
  237. /* ipv4 */
  238. he=gethostbyname(name);
  239. #ifdef USE_IPV6
  240. if(he==0){
  241. /*try ipv6*/
  242. #ifdef HAVE_GETHOSTBYNAME2
  243. he=gethostbyname2(name, AF_INET6);
  244. #elif defined HAVE_GETIPNODEBYNAME
  245. /* on solaris 8 getipnodebyname has a memory leak,
  246. * after some time calls to it will fail with err=3
  247. * solution: patch your solaris 8 installation */
  248. if (he2) freehostent(he2);
  249. he=he2=getipnodebyname(name, AF_INET6, 0, &err);
  250. #else
  251. #error neither gethostbyname2 or getipnodebyname present
  252. #endif
  253. }
  254. #endif
  255. return he;
  256. }
  257. #endif