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