/src/kamailio/src/core/resolve.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * resolver related functions |
3 | | * |
4 | | * Copyright (C) 2001-2003 FhG Fokus |
5 | | * |
6 | | * This file is part of Kamailio, a free SIP server. |
7 | | * |
8 | | * Kamailio is free software; you can redistribute it and/or modify |
9 | | * it under the terms of the GNU General Public License as published by |
10 | | * the Free Software Foundation; either version 2 of the License, or |
11 | | * (at your option) any later version |
12 | | * |
13 | | * Kamailio is distributed in the hope that it will be useful, |
14 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | | * GNU General Public License for more details. |
17 | | * |
18 | | * You should have received a copy of the GNU General Public License |
19 | | * along with this program; if not, write to the Free Software |
20 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
21 | | */ |
22 | | |
23 | | /*! |
24 | | * \file |
25 | | * \brief Kamailio core :: DNS resolver |
26 | | * \author andrei |
27 | | * \ingroup core |
28 | | * Module: \ref core |
29 | | */ |
30 | | |
31 | | #ifndef __resolve_h |
32 | | #define __resolve_h |
33 | | |
34 | | #include <sys/types.h> |
35 | | #include <sys/socket.h> |
36 | | #include <netinet/in.h> |
37 | | #include <netdb.h> |
38 | | #include <arpa/nameser.h> |
39 | | #include <resolv.h> |
40 | | #include "counters.h" |
41 | | #include "dns_func.h" |
42 | | |
43 | | #ifdef __OS_darwin |
44 | | #include <arpa/nameser_compat.h> |
45 | | #endif |
46 | | |
47 | | #include "ip_addr.h" |
48 | | #ifdef USE_DNS_CACHE |
49 | | #include "dns_wrappers.h" |
50 | | #endif |
51 | | |
52 | | |
53 | | #define MAX_QUERY_SIZE 8192 |
54 | | #define ANS_SIZE 8192 |
55 | 0 | #define DNS_HDR_SIZE 12 |
56 | 0 | #define MAX_DNS_NAME 256 |
57 | | #define MAX_DNS_STRING 255 |
58 | | |
59 | | #ifndef T_EBL |
60 | | /** not official yet - iEnum. */ |
61 | 0 | #define T_EBL 65300 |
62 | | #endif |
63 | | |
64 | | /* get_record flags */ |
65 | 0 | #define RES_ONLY_TYPE 1 /* return only the specified type records */ |
66 | 0 | #define RES_AR 2 /* return also the additional records */ |
67 | | |
68 | | /* counter for failed/slow DNS requests |
69 | | */ |
70 | | struct dns_counters_h |
71 | | { |
72 | | counter_handle_t failed_dns_req; |
73 | | counter_handle_t slow_dns_req; |
74 | | }; |
75 | | |
76 | | extern struct dns_counters_h dns_cnts_h; |
77 | | extern struct dns_func_t dns_func; |
78 | | |
79 | | /* query union*/ |
80 | | union dns_query |
81 | | { |
82 | | HEADER hdr; |
83 | | unsigned char buff[MAX_QUERY_SIZE]; |
84 | | }; |
85 | | |
86 | | |
87 | | /* rdata struct*/ |
88 | | struct rdata |
89 | | { |
90 | | unsigned short type; |
91 | | unsigned short pclass; |
92 | | unsigned int ttl; |
93 | | void *rdata; |
94 | | struct rdata *next; |
95 | | unsigned char name_len; /* name length w/o the terminating 0 */ |
96 | | char name[1]; /* null terminated name (len=name_len+1) */ |
97 | | }; |
98 | | /* real size of the structure */ |
99 | | #define RDATA_SIZE(s) (sizeof(struct rdata) + (s).name_len) /* +1-1 */ |
100 | | |
101 | | |
102 | | /* srv rec. struct*/ |
103 | | struct srv_rdata |
104 | | { |
105 | | unsigned short priority; |
106 | | unsigned short weight; |
107 | | unsigned short port; |
108 | | unsigned char name_len; /* name length w/o the terminating 0 */ |
109 | | char name[1]; /* null terminated name (len=name_len+1) */ |
110 | | }; |
111 | | |
112 | | |
113 | | /* real size of the structure */ |
114 | 0 | #define SRV_RDATA_SIZE(s) (sizeof(struct srv_rdata) + (s).name_len) |
115 | | |
116 | | /* naptr rec. struct*/ |
117 | | struct naptr_rdata |
118 | | { |
119 | | char *flags; /* points inside str_table */ |
120 | | char *services; /* points inside str_table */ |
121 | | char *regexp; /* points inside str_table */ |
122 | | char *repl; /* points inside str_table, null terminated */ |
123 | | |
124 | | unsigned short order; |
125 | | unsigned short pref; |
126 | | |
127 | | unsigned char flags_len; |
128 | | unsigned char services_len; |
129 | | unsigned char regexp_len; |
130 | | unsigned char repl_len; /* not currently used */ |
131 | | unsigned char skip_record; |
132 | | |
133 | | char str_table[1]; /* contains all the strings */ |
134 | | }; |
135 | | |
136 | | /* real size of the structure */ |
137 | | #define NAPTR_RDATA_SIZE(s) \ |
138 | 0 | (sizeof(struct naptr_rdata) + (s).flags_len + (s).services_len \ |
139 | 0 | + (s).regexp_len + (s).repl_len + 1 - 1) |
140 | | |
141 | | |
142 | | /* A rec. struct */ |
143 | | struct a_rdata |
144 | | { |
145 | | unsigned char ip[4]; |
146 | | }; |
147 | | |
148 | | struct aaaa_rdata |
149 | | { |
150 | | unsigned char ip6[16]; |
151 | | }; |
152 | | |
153 | | /* cname rec. struct*/ |
154 | | struct cname_rdata |
155 | | { |
156 | | unsigned char name_len; /* name length w/o the terminating 0 */ |
157 | | char name[1]; /* null terminated name (len=name_len+1) */ |
158 | | }; |
159 | | |
160 | | /* real size of the structure */ |
161 | 0 | #define CNAME_RDATA_SIZE(s) (sizeof(struct cname_rdata) + (s).name_len) |
162 | | |
163 | | /* dns character-string */ |
164 | | struct dns_cstr |
165 | | { |
166 | | char *cstr; /* pointer to null term. string */ |
167 | | unsigned char cstr_len; |
168 | | }; |
169 | | |
170 | | /* txt rec. struct */ |
171 | | struct txt_rdata |
172 | | { |
173 | | unsigned short cstr_no; /* number of strings */ |
174 | | unsigned short tslen; /* total strings table len */ |
175 | | struct dns_cstr txt[1]; /* at least 1 */ |
176 | | /* all txt[*].cstr point inside a string table at the end of the struct.*/ |
177 | | }; |
178 | | |
179 | | #define TXT_RDATA_SIZE(s) \ |
180 | 0 | (sizeof(struct txt_rdata) + ((s).cstr_no - 1) * sizeof(struct dns_cstr) \ |
181 | 0 | + (s).tslen) |
182 | | |
183 | | /* ebl rec. struct, see |
184 | | http://tools.ietf.org/html/draft-ietf-enum-branch-location-record-03 */ |
185 | | struct ebl_rdata |
186 | | { |
187 | | char *separator; /* points inside str_table */ |
188 | | char *apex; /* point inside str_table */ |
189 | | unsigned char separator_len; /* separator len w/o the terminating 0 */ |
190 | | unsigned char apex_len; /* apex len w/p the terminating 0 */ |
191 | | unsigned char position; |
192 | | char str_table[1]; /* contains the 2 strings: separator and apex */ |
193 | | }; |
194 | | #define EBL_RDATA_SIZE(s) \ |
195 | 0 | (sizeof(struct ebl_rdata) - 1 + (s).separator_len + 1 + (s).apex_len + 1) |
196 | | |
197 | | |
198 | | struct ptr_rdata |
199 | | { |
200 | | unsigned char ptrdname_len; /* name length w/o the terminating 0 */ |
201 | | char ptrdname[1]; /* null terminated name (len=name_len+1) */ |
202 | | }; |
203 | | /* real size of the structure */ |
204 | 0 | #define PTR_RDATA_SIZE(s) (sizeof(struct ptr_rdata) - 1 + (s).ptrdname_len + 1) |
205 | | |
206 | | |
207 | | #ifdef HAVE_RESOLV_RES |
208 | | int match_search_list(const struct __res_state *res, char *name); |
209 | | #endif |
210 | | struct rdata *get_record(char *name, int type, int flags); |
211 | | void free_rdata_list(struct rdata *head); |
212 | | |
213 | | |
214 | | #define rev_resolvehost(ip) \ |
215 | 0 | gethostbyaddr((char *)(ip)->u.addr, (ip)->len, (ip)->af) |
216 | | |
217 | | |
218 | | #define HEX2I(c) \ |
219 | 0 | ((((c) >= '0') && ((c) <= '9')) ? (c) - '0' \ |
220 | 0 | : (((c) >= 'A') && ((c) <= 'F')) ? ((c) - 'A') + 10 \ |
221 | 0 | : (((c) >= 'a') && ((c) <= 'f')) ? ((c) - 'a') + 10 \ |
222 | 0 | : -1) |
223 | | |
224 | | |
225 | | int str2ipbuf(str *st, ip_addr_t *ipb); |
226 | | int str2ip6buf(str *st, ip_addr_t *ipb); |
227 | | int str2ipxbuf(str *st, ip_addr_t *ipb); |
228 | | ip_addr_t *str2ip(str *st); |
229 | | ip_addr_t *str2ip6(str *st); |
230 | | ip_addr_t *str2ipx(str *st); |
231 | | |
232 | | struct hostent *_sip_resolvehost(str *name, unsigned short *port, char *proto); |
233 | | |
234 | | |
235 | | /* gethostbyname wrapper, handles ip/ipv6 automatically */ |
236 | | static inline struct hostent *_resolvehost(char *name) |
237 | 0 | { |
238 | 0 | static struct hostent *he = 0; |
239 | | #ifdef HAVE_GETIPNODEBYNAME |
240 | | int err; |
241 | | static struct hostent *he2 = 0; |
242 | | #endif |
243 | | #ifndef DNS_IP_HACK |
244 | | int len; |
245 | | #endif |
246 | 0 | #ifdef DNS_IP_HACK |
247 | 0 | struct ip_addr *ip; |
248 | 0 | str s; |
249 | |
|
250 | 0 | s.s = (char *)name; |
251 | 0 | s.len = strlen(name); |
252 | | |
253 | | /* check if it's an ip address */ |
254 | 0 | if(((ip = str2ip(&s)) != 0) || ((ip = str2ip6(&s)) != 0)) { |
255 | | /* we are lucky, this is an ip address */ |
256 | 0 | return ip_addr2he(&s, ip); |
257 | 0 | } |
258 | | |
259 | | #else /* DNS_IP_HACK */ |
260 | | len = 0; |
261 | | if(*name == '[') { |
262 | | len = strlen(name); |
263 | | if(len && (name[len - 1] == ']')) { |
264 | | name[len - 1] = 0; /* remove '[' */ |
265 | | name++; /* skip '[' */ |
266 | | goto skip_ipv4; |
267 | | } |
268 | | } |
269 | | #endif |
270 | | /* ipv4 */ |
271 | 0 | he = dns_func.sr_gethostbyname(name); |
272 | |
|
273 | 0 | if(he == 0 && cfg_get(core, core_cfg, dns_try_ipv6)) { |
274 | | #ifndef DNS_IP_HACK |
275 | | skip_ipv4: |
276 | | #endif |
277 | | /*try ipv6*/ |
278 | 0 | #ifdef HAVE_GETHOSTBYNAME2 |
279 | 0 | he = dns_func.sr_gethostbyname2(name, AF_INET6); |
280 | | #elif defined HAVE_GETIPNODEBYNAME |
281 | | /* on solaris 8 getipnodebyname has a memory leak, |
282 | | * after some time calls to it will fail with err=3 |
283 | | * solution: patch your solaris 8 installation */ |
284 | | if(he2) |
285 | | freehostent(he2); |
286 | | he = he2 = getipnodebyname(name, AF_INET6, 0, &err); |
287 | | #else |
288 | | #error neither gethostbyname2 or getipnodebyname present |
289 | | #endif |
290 | | #ifndef DNS_IP_HACK |
291 | | if(len) |
292 | | name[len - 2] = ']'; /* restore */ |
293 | | #endif |
294 | 0 | } |
295 | 0 | return he; |
296 | 0 | } Unexecuted instantiation: main.c:_resolvehost Unexecuted instantiation: resolve.c:_resolvehost Unexecuted instantiation: route.c:_resolvehost Unexecuted instantiation: select_core.c:_resolvehost Unexecuted instantiation: socket_info.c:_resolvehost Unexecuted instantiation: action.c:_resolvehost Unexecuted instantiation: cfg.tab.c:_resolvehost Unexecuted instantiation: cfg_core.c:_resolvehost Unexecuted instantiation: dns_cache.c:_resolvehost Unexecuted instantiation: dst_blocklist.c:_resolvehost Unexecuted instantiation: forward.c:_resolvehost Unexecuted instantiation: ip_addr.c:_resolvehost Unexecuted instantiation: kemi.c:_resolvehost Unexecuted instantiation: msg_translator.c:_resolvehost Unexecuted instantiation: proxy.c:_resolvehost |
297 | | |
298 | | |
299 | | int resolv_init(void); |
300 | | |
301 | | /* callback/fixup functions executed by the configuration framework */ |
302 | | void resolv_reinit(str *gname, str *name); |
303 | | int dns_reinit_fixup(void *handle, str *gname, str *name, void **val); |
304 | | int dns_try_ipv6_fixup(void *handle, str *gname, str *name, void **val); |
305 | | void reinit_proto_prefs(str *gname, str *name); |
306 | | |
307 | | struct dns_srv_proto |
308 | | { |
309 | | char proto; |
310 | | int proto_pref; |
311 | | }; |
312 | | void create_srv_name(char proto, str *name, char *srv); |
313 | | size_t create_srv_pref_list(char *proto, struct dns_srv_proto *list); |
314 | | |
315 | | #ifdef DNS_WATCHDOG_SUPPORT |
316 | | /* callback function that is called by the child processes |
317 | | * when they reinitialize the resolver |
318 | | * |
319 | | * Note, that this callback is called by each chiled process separately!!! |
320 | | * If the callback is registered after forking, only the child process |
321 | | * that installs the hook will call the callback. |
322 | | */ |
323 | | typedef void (*on_resolv_reinit)(str *); |
324 | | int register_resolv_reinit_cb(on_resolv_reinit cb); |
325 | | #endif |
326 | | |
327 | | |
328 | | int sip_hostport2su( |
329 | | union sockaddr_union *su, str *host, unsigned short port, char *proto); |
330 | | |
331 | | |
332 | | /* wrappers */ |
333 | | #ifdef USE_DNS_CACHE |
334 | 0 | #define resolvehost dns_resolvehost |
335 | 0 | #define sip_resolvehost dns_sip_resolvehost |
336 | | #else |
337 | | #define resolvehost _resolvehost |
338 | | #define sip_resolvehost _sip_resolvehost |
339 | | #endif |
340 | | |
341 | | |
342 | | #ifdef USE_NAPTR |
343 | | /* NAPTR helper functions */ |
344 | | typedef unsigned int naptr_bmp_t; /* type used for keeping track of tried |
345 | | naptr records*/ |
346 | 0 | #define MAX_NAPTR_RRS (sizeof(naptr_bmp_t) * 8) |
347 | | |
348 | | /* use before first call to naptr_sip_iterate */ |
349 | | #define naptr_iterate_init(bmp) \ |
350 | 0 | do { \ |
351 | 0 | *(bmp) = 0; \ |
352 | 0 | } while(0) |
353 | | |
354 | | struct rdata *naptr_sip_iterate(struct rdata *naptr_head, naptr_bmp_t *tried, |
355 | | str *srv_name, char *proto); |
356 | | /* returns sip proto if valis sip naptr record, .-1 otherwise */ |
357 | | char naptr_get_sip_proto(struct naptr_rdata *n); |
358 | | /* returns true if new_proto is preferred over old_proto */ |
359 | | int naptr_proto_preferred(char new_proto, char old_proto); |
360 | | /* returns true if we support the protocol */ |
361 | | int naptr_proto_supported(char proto); |
362 | | /* choose between 2 naptr records, should take into account local |
363 | | * preferences too |
364 | | * returns 1 if the new record was selected, 0 otherwise */ |
365 | | int naptr_choose(struct naptr_rdata **crt, char *crt_proto, |
366 | | struct naptr_rdata *n, char n_proto); |
367 | | |
368 | | #endif /* USE_NAPTR */ |
369 | | |
370 | | struct hostent *no_naptr_srv_sip_resolvehost( |
371 | | str *name, unsigned short *port, char *proto); |
372 | | |
373 | | #endif |