- sun fixes
[sip-router] / resolve.h
1 /*
2  * $Id$
3  *
4  * resolver related functions
5  */
6
7
8 #ifndef __resolve_h
9 #define __resolve_h
10
11 #include <sys/types.h>
12 #include <sys/socket.h>
13 #include <netdb.h>
14 #include <arpa/nameser.h>
15
16 #include "ip_addr.h"
17
18
19 #define MAX_QUERY_SIZE 8192
20 #define ANS_SIZE       8192
21 #define DNS_HDR_SIZE     12
22 #define MAX_DNS_NAME 256
23
24
25
26 /* query union*/
27 union dns_query{
28         HEADER hdr;
29         unsigned char buff[MAX_QUERY_SIZE];
30 };
31
32
33 /* rdata struct*/
34 struct rdata {
35         unsigned short type;
36         unsigned short class;
37         unsigned int   ttl;
38         void* rdata;
39         struct rdata* next;
40 };
41
42
43 /* srv rec. struct*/
44 struct srv_rdata {
45         unsigned short priority;
46         unsigned short weight;
47         unsigned short port;
48         unsigned int name_len;
49         char name[MAX_DNS_NAME];
50 };
51
52
53 /* A rec. struct */
54 struct a_rdata {
55         unsigned char ip[4];
56 };
57
58 struct aaaa_rdata {
59         unsigned char ip6[16];
60 };
61
62 /* cname rec. struct*/
63 struct cname_rdata {
64         char name[MAX_DNS_NAME];
65 };
66
67
68
69 struct rdata* get_record(char* name, int type);
70 void free_rdata_list(struct rdata* head);
71
72
73
74
75 #define rev_resolvehost(ip) gethostbyaddr((ip)->u.addr, (ip)->len, (ip)->af);
76
77
78
79 #define HEX2I(c) \
80         (       (((c)>='0') && ((c)<='9'))? (c)-'0' :  \
81                 (((c)>='A') && ((c)<='F'))? ((c)-'A')+10 : \
82                 (((c)>='a') && ((c)<='f'))? ((c)-'a')+10 : -1 )
83
84
85
86
87
88 /* converts a str to an ipv4 address, returns the address or 0 on error
89    Warning: the result is a pointer to a statically allocated structure */
90 static inline struct ip_addr* str2ip(unsigned char* str, unsigned int len)
91 {
92         int i;
93         unsigned char *limit;
94         unsigned char *init;
95         static struct ip_addr ip;
96
97         /*init*/
98         ip.u.addr32[0]=0;
99         i=0;
100         limit=str+len;
101         init=str;
102
103         for(;str<limit ;str++){
104                 if (*str=='.'){
105                                 i++;
106                                 if (i>3) goto error_dots;
107                 }else if ( (*str <= '9' ) && (*str >= '0') ){
108                                 ip.u.addr[i]=ip.u.addr[i]*10+*str-'0';
109                 }else{
110                                 //error unknown char
111                                 goto error_char;
112                 }
113         }
114         ip.af=AF_INET;
115         ip.len=4;
116         
117         return &ip;
118
119 error_dots:
120         DBG("str2ip: ERROR: too many dots in [%.*s]\n", (int)len, init);
121         return 0;
122 error_char:
123         DBG("str2ip: WARNING: unexpected char %c in %.*s\n", *str,(int)len, init);
124         return 0;
125 }
126
127
128
129 /* returns an ip_addr struct.; on error returns 0
130  * the ip_addr struct is static, so subsequent calls will destroy its content*/
131 static inline struct ip_addr* str2ip6(unsigned char* str, unsigned int len)
132 {
133         int i, idx1, rest;
134         int no_colons;
135         int double_colon;
136         int hex;
137         static struct ip_addr ip;
138         unsigned short* addr_start;
139         unsigned short addr_end[8];
140         unsigned short* addr;
141         unsigned char* limit;
142         unsigned char* init;
143         
144         /* init */
145         init=str;
146         i=idx1=rest=0;
147         double_colon=0;
148         no_colons=0;
149         ip.af=AF_INET6;
150         ip.len=16;
151         addr_start=ip.u.addr16;
152         addr=addr_start;
153         limit=str+len;
154         memset(addr_start, 0 , 8*sizeof(unsigned short));
155         memset(addr_end, 0 , 8*sizeof(unsigned short));
156         
157         for (; str<limit; str++){
158                 if (*str==':'){
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(*str))>=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         rest=8-i-idx1;
185         memcpy(addr_start+idx1+rest, addr_end, i*sizeof(unsigned short));
186         return &ip;
187
188 error_too_many_colons:
189         DBG("str2ip6: ERROR: too many colons in [%.*s]\n", (int) len, init);
190         return 0;
191
192 error_too_few_colons:
193         DBG("str2ip6: ERROR: too few colons in [%.*s]\n", (int) len, init);
194         return 0;
195
196 error_colons:
197         DBG("str2ip6: ERROR: too many double colons in [%.*s]\n", (int) len, init);
198         return 0;
199
200 error_char:
201         DBG("str2ip6: WARNING: unexpected char %c in  [%.*s]\n", *str, (int) len,
202                         init);
203         return 0;
204 }
205
206
207
208 struct hostent* sip_resolvehost(char* name, unsigned short* port);
209
210
211
212 /* gethostbyname wrappers
213  * use this, someday they will use a local cache */
214
215 static inline struct hostent* resolvehost(const char* name)
216 {
217         static struct hostent* he=0;
218 #ifdef __sun__
219         int err;
220 #endif
221 #ifdef DNS_IP_HACK
222         struct ip_addr* ip;
223         int len;
224         
225         len=strlen(name);
226         /* check if it's an ip address */
227         if ( ((ip=str2ip(name, len))!=0)
228 #ifdef  USE_IPV6
229                   || ((ip=str2ip6(name, len))!=0)
230 #endif
231                 ){
232                 /* we are lucky, this is an ip address */
233                 return ip_addr2he(name, len, ip);
234         }
235         
236 #endif
237         /* ipv4 */
238 #ifdef __sun__
239         if (he) freehostent(he);
240         he=getipnodebyname(name, AF_INET, 0, &err);
241 #else
242         he=gethostbyname(name);
243 #endif
244 #ifdef USE_IPV6
245         if(he==0){
246                 /*try ipv6*/
247         #ifdef __sun__
248                 he=getipnodebyname(name, AF_INET6, 0, &err);
249         #else
250                 he=gethostbyname2(name, AF_INET6);
251         #endif
252         }
253 #endif
254         return he;
255 }
256
257
258
259 #endif