File: | libsofia-sip-ua/sresolv/sres_sip.c |
Warning: | line 1471, column 12 Although the value stored to 'j' is used in the enclosing expression, the value is never actually read from 'j' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* |
2 | * This file is part of the Sofia-SIP package |
3 | * |
4 | * Copyright (C) 2007 Nokia Corporation. |
5 | * |
6 | * Contact: Pekka Pessi <pekka.pessi@nokia.com> |
7 | * |
8 | * This library is free software; you can redistribute it and/or |
9 | * modify it under the terms of the GNU Lesser General Public License |
10 | * as published by the Free Software Foundation; either version 2.1 of |
11 | * the License, or (at your option) any later version. |
12 | * |
13 | * This library is distributed in the hope that it will be useful, but |
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
16 | * Lesser General Public License for more details. |
17 | * |
18 | * You should have received a copy of the GNU Lesser General Public |
19 | * License along with this library; if not, write to the Free Software |
20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA |
21 | * 02110-1301 USA |
22 | * |
23 | */ |
24 | |
25 | /**@CFILE sres_sip.c |
26 | * @brief RFC3263 SIP Resolver |
27 | * |
28 | * @author Pekka Pessi <Pekka.Pessi@nokia.com> |
29 | * |
30 | * @sa |
31 | * @RFC3263 |
32 | */ |
33 | |
34 | #include "config.h" |
35 | |
36 | struct sres_sip_tport; |
37 | struct srs_step; |
38 | struct srs_hint; |
39 | struct sres_sip_s; |
40 | |
41 | #include <sofia-sip/su_string.h> |
42 | #include <sofia-sip/hostdomain.h> |
43 | #include <sofia-sip/url.h> |
44 | #include <sofia-sip/su_errno.h> |
45 | #include <sofia-sip/su.h> |
46 | |
47 | #define SRES_CONTEXT_Tstruct srs_step struct srs_step |
48 | |
49 | #include <sofia-sip/su_uniqueid.h> |
50 | #include "sofia-sip/sres_sip.h" |
51 | #include "sofia-resolv/sres.h" |
52 | #include "sofia-resolv/sres_record.h" |
53 | |
54 | #include <stddef.h> |
55 | #include <stdlib.h> |
56 | #include <assert.h> |
57 | #include <errno(*__errno_location ()).h> |
58 | |
59 | #define SU_LOGsresolv_log sresolv_log |
60 | |
61 | #include <sofia-sip/su_debug.h> |
62 | |
63 | /** |
64 | * For each transport, we have name used by tport module, SRV prefixes used |
65 | * for resolving, and NAPTR service/conversion. |
66 | */ |
67 | struct sres_sip_tport { |
68 | int stp_type; /**< Default protocol for this URL type */ |
69 | uint16_t stp_number; /**< Protocol number used by tport module */ |
70 | uint16_t stp_port; /**< Default port number */ |
71 | char stp_name[6]; /**< Named used by tport module */ |
72 | char stp_prefix[14]; /**< Prefix for SRV domains */ |
73 | char stp_service[10]; /**< NAPTR service (empty if none) */ |
74 | }; |
75 | |
76 | #define N_TRANSPORTS20 20 |
77 | |
78 | static struct sres_sip_tport const sres_sip_tports[N_TRANSPORTS20] = { |
79 | { url_sip, TPPROTO_UDPTPPROTO_UDP, 5060, "udp", "_sip._udp.", "SIP+D2U" }, |
80 | { url_sip, TPPROTO_TCPTPPROTO_TCP, 5060, "tcp", "_sip._tcp.", "SIP+D2T" }, |
81 | { url_sips, TPPROTO_TLSTPPROTO_TLS, 5061, "tls", "_sips._tcp.", "SIPS+D2T" }, |
82 | { url_any, TPPROTO_SCTPTPPROTO_SCTP, 5060, "sctp", "_sip._sctp.", "SIP+D2S" }, |
83 | }; |
84 | |
85 | struct srs_step; |
86 | struct srs_hint; |
87 | |
88 | struct sres_sip_s |
89 | { |
90 | su_home_t srs_home[1]; |
91 | sres_resolver_t *srs_resolver; |
92 | |
93 | sres_sip_notify_f *srs_callback; |
94 | sres_sip_magic_t *srs_magic; |
95 | |
96 | /* What we are resolving */ |
97 | url_t *srs_url; |
98 | |
99 | /* Parsed */ |
100 | char const *srs_target; |
101 | short srs_maddr; |
102 | short srs_transport; /**< URL-specified transport protocol */ |
103 | uint16_t srs_port; |
104 | |
105 | int srs_error; |
106 | |
107 | /** Resolving steps (to take) */ |
108 | struct srs_step *srs_head, **srs_queue; /**< List of subqueries */ |
109 | struct srs_step **srs_process; /**< Next result to process */ |
110 | struct srs_step **srs_send; /**< Next query to make */ |
111 | |
112 | /** Results */ |
113 | su_addrinfo_t *srs_results, **srs_next, **srs_tail; |
114 | |
115 | unsigned srs_try_naptr:1, srs_try_srv:1, srs_try_a:1; |
116 | unsigned srs_canonname:1, srs_numeric:1; |
117 | |
118 | unsigned srs_blocking:1, srs_complete:1, :0; |
119 | |
120 | /** Hints for this request. */ |
121 | struct srs_hint { |
122 | struct sres_sip_tport const *hint_stp; |
123 | uint16_t hint_qtype; |
124 | uint16_t hint_port; |
125 | } srs_hints[2 * N_TRANSPORTS20 + 2]; |
126 | /* srs_hints[0] is ignored, srs_hints[2*N_TRANSPORTS + 1] is sentinel. */ |
127 | }; |
128 | |
129 | /** Intermediate steps */ |
130 | struct srs_step |
131 | { |
132 | struct srs_step *sp_next; |
133 | sres_sip_t *sp_srs; /**< Backpointer */ |
134 | struct srs_step *sp_already; /**< Step with identical query |
135 | - itself if first one */ |
136 | struct srs_step *sp_trace; /**< Step that resulted in this step */ |
137 | sres_record_t const *sp_origin; /**< DNS record that resulted in this step */ |
138 | |
139 | char const *sp_target; |
140 | sres_query_t *sp_query; |
141 | |
142 | /** Query status. |
143 | * |
144 | * STEP_NEW (-4) when created, |
145 | * STEP_QUEUED (-3) when queued, |
146 | * STEP_CACHED (-2) when found cached response |
147 | * STEP_SENT (-1) when query has been sent |
148 | * (positive) status from response otherwise |
149 | */ |
150 | int sp_status; |
151 | |
152 | sres_record_t **sp_results; |
153 | |
154 | uint16_t sp_hint; /* Number of hint */ |
155 | |
156 | uint16_t sp_port; /* port number */ |
157 | uint16_t sp_type; /* query type */ |
158 | uint16_t sp_prefer; /* order */ |
159 | uint16_t sp_priority; /* priority */ |
160 | uint16_t sp_weight; /* weight */ |
161 | |
162 | uint16_t sp_grayish; /* candidate for graylisting */ |
163 | }; |
164 | |
165 | #define SP_HINT(sp)((sp)->sp_hint ? &(sp)->sp_srs[sp->sp_hint] : (( void*)0)) ((sp)->sp_hint ? &(sp)->sp_srs[sp->sp_hint] : NULL((void*)0)) |
166 | #define SP_STP(sp)((sp)->sp_hint ? (sp)->sp_srs[sp->sp_hint].hint_stp : ((void*)0)); ((sp)->sp_hint ? (sp)->sp_srs[sp->sp_hint].hint_stp : NULL((void*)0)); |
167 | |
168 | enum { |
169 | STEP_NEW = -4, |
170 | STEP_QUEUED = -3, |
171 | STEP_CACHED = -2, |
172 | STEP_SENT = -1, |
173 | STEP_OK = 0 |
174 | }; |
175 | |
176 | static void _sres_sip_destruct(void *_srs); |
177 | static sres_sip_t *sres_sip_fatal(sres_sip_t *srs, int error); |
178 | static void sres_sip_hint(sres_sip_t *srs, int qtype, int protocol); |
179 | static int sres_sip_url_transport(url_t const *uri); |
180 | static char const *sres_sip_transport_name(int number); |
181 | void sres_sip_graylist(sres_sip_t *srs, struct srs_step *step); |
182 | |
183 | static int sres_sip_is_waiting(sres_sip_t const *srs); |
184 | static void sres_sip_return_results(sres_sip_t *srs, int final); |
185 | |
186 | static void sres_sip_try_next_steps(sres_sip_t *srs); |
187 | static void sres_sip_try_naptr_steps(sres_sip_t *srs); |
188 | static void sres_sip_try_srv_steps(sres_sip_t *srs); |
189 | static void sres_sip_try_a_aaaa_steps(sres_sip_t *srs); |
190 | |
191 | static struct srs_step *sres_sip_step_new( |
192 | sres_sip_t *srs, |
193 | int type, |
194 | char const *prefix, |
195 | char const *domain); |
196 | |
197 | static void sres_sip_append_step(sres_sip_t *srs, |
198 | struct srs_step *step); |
199 | |
200 | static void sres_sip_insert_step(sres_sip_t *srs, |
201 | struct srs_step *step); |
202 | |
203 | static int sres_sip_send_steps(sres_sip_t *srs); |
204 | static void sres_sip_answer(struct srs_step *step, |
205 | sres_query_t *q, |
206 | sres_record_t *answers[]); |
207 | static int sres_sip_status_of_answers(sres_record_t *answers[], uint16_t type); |
208 | static int sres_sip_count_answers(sres_record_t *answers[], uint16_t type); |
209 | static void sres_sip_log_answers(sres_sip_t *srs, |
210 | struct srs_step *step, |
211 | sres_record_t *answers[]); |
212 | |
213 | static int sres_sip_process(sres_sip_t *srs); |
214 | |
215 | static void sres_sip_process_naptr(sres_sip_t *srs, |
216 | struct srs_step *nq, |
217 | sres_record_t *answers[]); |
218 | static void sres_sip_sort_naptr(sres_record_t *answers[]); |
219 | |
220 | static void sres_sip_step_by_naptr(sres_sip_t *srs, |
221 | struct srs_step *, |
222 | uint16_t hint, |
223 | sres_naptr_record_t const *na); |
224 | |
225 | static void sres_sip_process_srv(sres_sip_t *srs, |
226 | struct srs_step *nq, |
227 | sres_record_t *answers[]); |
228 | |
229 | static void sres_sip_sort_srv(sres_record_t *answers[]); |
230 | |
231 | #if SU_HAVE_IN61 |
232 | static void sres_sip_process_aaaa(sres_sip_t *srs, struct srs_step *, |
233 | sres_record_t *answers[]); |
234 | #endif |
235 | static void sres_sip_process_a(sres_sip_t *srs, struct srs_step *, |
236 | sres_record_t *answers[]); |
237 | |
238 | static void sres_sip_process_cname(sres_sip_t *srs, |
239 | struct srs_step *step0, |
240 | sres_record_t *answers[]); |
241 | |
242 | static void sres_sip_process_numeric(sres_sip_t *srs); |
243 | |
244 | static void sres_sip_append_result(sres_sip_t *srs, |
245 | su_addrinfo_t const *result); |
246 | |
247 | /** Resolve a SIP uri. |
248 | * |
249 | */ |
250 | sres_sip_t * |
251 | sres_sip_new(sres_resolver_t *sres, |
252 | url_string_t const *uri, |
253 | su_addrinfo_t const *hints, |
254 | int naptr, int srv, |
255 | sres_sip_notify_f *callback, |
256 | sres_sip_magic_t *magic) |
257 | { |
258 | sres_sip_t *srs; |
259 | url_t *u; |
260 | char const *target, *port; |
261 | su_addrinfo_t const hints0 = { 0 }; |
262 | int numeric; |
263 | int transport; |
264 | isize_t maddr; |
265 | |
266 | if (sres == NULL((void*)0) || uri == NULL((void*)0)) |
267 | return su_seterrno(EFAULT14), NULL((void*)0); |
268 | |
269 | srs = su_home_new(sizeof *srs); |
270 | if (srs == NULL((void*)0)) |
271 | return NULL((void*)0); |
272 | |
273 | srs->srs_queue = srs->srs_send = srs->srs_process = &srs->srs_head; |
274 | srs->srs_next = srs->srs_tail = &srs->srs_results; |
275 | |
276 | su_home_destructor(srs->srs_home, _sres_sip_destruct); |
277 | |
278 | srs->srs_url = u = url_hdup(srs->srs_home, (url_t *)uri); |
279 | if (u == NULL((void*)0)) |
280 | return sres_sip_fatal(srs, SRES_SIP_ERR_BAD_URI); |
281 | if (u->url_type != url_sip && u->url_type != url_urn && u->url_type != url_sips) |
282 | return sres_sip_fatal(srs, SRES_SIP_ERR_BAD_URI); |
283 | |
284 | /* RFC 3263: |
285 | We define TARGET as the value of the maddr parameter of the URI, if |
286 | present, otherwise, the host value of the hostport component of the |
287 | URI. |
288 | */ |
289 | maddr = url_param(u->url_params, "maddr=", NULL((void*)0), 0); |
290 | |
291 | if (maddr) { |
292 | target = su_alloc(srs->srs_home, maddr); |
293 | url_param(u->url_params, "maddr=", (char *)target, maddr); |
294 | } |
295 | else { |
296 | target = u->url_host; |
297 | } |
298 | |
299 | if (!target) |
300 | return sres_sip_fatal(srs, SRES_SIP_ERR_BAD_URI); |
301 | |
302 | srs->srs_target = target; |
303 | srs->srs_maddr = maddr != 0; |
304 | port = u->url_port; |
305 | |
306 | srs->srs_transport = transport = sres_sip_url_transport(u); |
307 | if (transport == -1) |
308 | return sres_sip_fatal(srs, SRES_SIP_ERR_NO_TPORT); |
309 | |
310 | if (transport && u->url_type == url_sips) |
311 | /* <sips:host.domain;transport=tcp> */ |
312 | srs->srs_transport = transport | TPPROTO_SECURE; |
313 | |
314 | numeric = host_is_ip_address(target); |
315 | |
316 | if (numeric) { |
317 | naptr = 0, srv = 0; |
318 | if (!port || !strlen(port)) |
319 | port = url_port_default((enum url_type_e)u->url_type); |
320 | } |
321 | |
322 | /* RFC 3263: |
323 | If the TARGET was not a numeric IP address, but a port is present in |
324 | the URI, the client performs an A or AAAA record lookup of the domain |
325 | name. The result will be a list of IP addresses, each of which can |
326 | be contacted at the specific port from the URI and transport protocol |
327 | determined previously. The client SHOULD try the first record. If |
328 | an attempt should fail, based on the definition of failure in Section |
329 | 4.3, the next SHOULD be tried, and if that should fail, the next |
330 | SHOULD be tried, and so on. |
331 | |
332 | This is a change from RFC 2543. Previously, if the port was |
333 | explicit, but with a value of 5060, SRV records were used. Now, A |
334 | or AAAA records will be used. |
335 | */ |
336 | if (port && strlen(port)) { |
337 | unsigned long number; |
338 | naptr = 0, srv = 0; |
339 | srs->srs_port = number = strtoul(port, 0, 10); |
340 | if (number == 0 || number >= 65536) |
341 | return sres_sip_fatal(srs, SRES_SIP_ERR_BAD_URI); |
342 | } |
343 | |
344 | if (hints == NULL((void*)0)) |
345 | hints = &hints0; |
346 | |
347 | srs->srs_canonname = (hints->ai_flags & AI_CANONNAME0x0002) != 0; |
348 | srs->srs_numeric = (hints->ai_flags & AI_NUMERICHOST0x0004) != 0; |
349 | |
350 | srs->srs_resolver = sres_resolver_ref(sres); |
351 | srs->srs_blocking = sres_is_blocking(sres); |
352 | |
353 | srs->srs_try_srv = srv; |
354 | srs->srs_try_naptr = naptr; |
355 | srs->srs_try_a = !numeric; |
356 | |
357 | for (;hints; hints = hints->ai_next) { |
358 | #if SU_HAVE_IN61 |
359 | if (hints->ai_family == 0 || hints->ai_family == AF_INET610) { |
360 | sres_sip_hint(srs, sres_type_aaaa, hints->ai_protocol); |
361 | } |
362 | #endif |
363 | if (hints->ai_family == 0 || hints->ai_family == AF_INET2) { |
364 | sres_sip_hint(srs, sres_type_a, hints->ai_protocol); |
365 | } |
366 | } |
367 | |
368 | SU_DEBUG_5(("srs(%p): resolving <%s:%s%s%s%s%s%s%s>\n",(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 375, "srs(%p): resolving <%s:%s%s%s%s%s%s%s>\n" , (void *)srs, u->url_scheme, u->url_host, u->url_port ? ":" : "", u->url_port ? u->url_port : "", maddr ? ";maddr=" : "", maddr ? target : "", transport ? ";transport=" : "", transport ? sres_sip_transport_name(transport) : "")) : (void)0) |
369 | (void *)srs,(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 375, "srs(%p): resolving <%s:%s%s%s%s%s%s%s>\n" , (void *)srs, u->url_scheme, u->url_host, u->url_port ? ":" : "", u->url_port ? u->url_port : "", maddr ? ";maddr=" : "", maddr ? target : "", transport ? ";transport=" : "", transport ? sres_sip_transport_name(transport) : "")) : (void)0) |
370 | u->url_scheme, u->url_host,(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 375, "srs(%p): resolving <%s:%s%s%s%s%s%s%s>\n" , (void *)srs, u->url_scheme, u->url_host, u->url_port ? ":" : "", u->url_port ? u->url_port : "", maddr ? ";maddr=" : "", maddr ? target : "", transport ? ";transport=" : "", transport ? sres_sip_transport_name(transport) : "")) : (void)0) |
371 | u->url_port ? ":" : "", u->url_port ? u->url_port : "",(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 375, "srs(%p): resolving <%s:%s%s%s%s%s%s%s>\n" , (void *)srs, u->url_scheme, u->url_host, u->url_port ? ":" : "", u->url_port ? u->url_port : "", maddr ? ";maddr=" : "", maddr ? target : "", transport ? ";transport=" : "", transport ? sres_sip_transport_name(transport) : "")) : (void)0) |
372 | maddr ? ";maddr=" : "",(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 375, "srs(%p): resolving <%s:%s%s%s%s%s%s%s>\n" , (void *)srs, u->url_scheme, u->url_host, u->url_port ? ":" : "", u->url_port ? u->url_port : "", maddr ? ";maddr=" : "", maddr ? target : "", transport ? ";transport=" : "", transport ? sres_sip_transport_name(transport) : "")) : (void)0) |
373 | maddr ? target : "",(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 375, "srs(%p): resolving <%s:%s%s%s%s%s%s%s>\n" , (void *)srs, u->url_scheme, u->url_host, u->url_port ? ":" : "", u->url_port ? u->url_port : "", maddr ? ";maddr=" : "", maddr ? target : "", transport ? ";transport=" : "", transport ? sres_sip_transport_name(transport) : "")) : (void)0) |
374 | transport ? ";transport=" : "",(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 375, "srs(%p): resolving <%s:%s%s%s%s%s%s%s>\n" , (void *)srs, u->url_scheme, u->url_host, u->url_port ? ":" : "", u->url_port ? u->url_port : "", maddr ? ";maddr=" : "", maddr ? target : "", transport ? ";transport=" : "", transport ? sres_sip_transport_name(transport) : "")) : (void)0) |
375 | transport ? sres_sip_transport_name(transport) : ""))(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 375, "srs(%p): resolving <%s:%s%s%s%s%s%s%s>\n" , (void *)srs, u->url_scheme, u->url_host, u->url_port ? ":" : "", u->url_port ? u->url_port : "", maddr ? ";maddr=" : "", maddr ? target : "", transport ? ";transport=" : "", transport ? sres_sip_transport_name(transport) : "")) : (void)0); |
376 | |
377 | if (numeric) |
378 | sres_sip_process_numeric(srs); |
379 | else |
380 | sres_sip_next_step(srs); |
381 | |
382 | srs->srs_callback = callback; |
383 | srs->srs_magic = magic; |
384 | |
385 | return srs; |
386 | } |
387 | |
388 | sres_sip_t * |
389 | sres_sip_ref(sres_sip_t *srs) |
390 | { |
391 | return (sres_sip_t *)su_home_ref(srs->srs_home); |
392 | } |
393 | |
394 | void |
395 | sres_sip_unref(sres_sip_t *srs) |
396 | { |
397 | su_home_unref(srs->srs_home); |
398 | } |
399 | |
400 | static void |
401 | _sres_sip_destruct(void *_srs) |
402 | { |
403 | sres_sip_t *srs = _srs; |
404 | sres_resolver_t *sres = srs->srs_resolver; |
405 | struct srs_step *step; |
406 | |
407 | SU_DEBUG_5(("srs(%p): destroyed\n", (void *) (_srs)))(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 407, "srs(%p): destroyed\n", (void * ) (_srs))) : (void)0); |
408 | |
409 | srs->srs_resolver = NULL((void*)0); |
410 | |
411 | for (step = srs->srs_head; step; step = step->sp_next) { |
412 | if (step->sp_already == step) |
413 | sres_free_answers(sres, step->sp_results); |
414 | step->sp_results = NULL((void*)0); |
415 | sres_query_bind(step->sp_query, NULL((void*)0), NULL((void*)0)), step->sp_query = NULL((void*)0); |
416 | } |
417 | |
418 | sres_resolver_unref(sres); |
419 | } |
420 | |
421 | int |
422 | sres_sip_error(sres_sip_t *srs) |
423 | { |
424 | return srs ? srs->srs_error : SRES_SIP_ERR_FAULT; |
425 | } |
426 | |
427 | su_addrinfo_t const * |
428 | sres_sip_results(sres_sip_t *srs) |
429 | { |
430 | return srs ? srs->srs_results : NULL((void*)0); |
431 | } |
432 | |
433 | su_addrinfo_t const * |
434 | sres_sip_next(sres_sip_t *srs) |
435 | { |
436 | su_addrinfo_t *next = NULL((void*)0); |
437 | |
438 | if (srs) { |
439 | next = *srs->srs_next; |
440 | if (next) |
441 | srs->srs_next = &next->ai_next; |
442 | } |
443 | |
444 | return next; |
445 | } |
446 | |
447 | static sres_sip_t * |
448 | sres_sip_fatal(sres_sip_t *srs, int error) |
449 | { |
450 | srs->srs_error = error; |
451 | srs->srs_try_naptr = 0, srs->srs_try_srv = 0, srs->srs_try_a = 0; |
452 | return srs; |
453 | } |
454 | |
455 | static void |
456 | sres_sip_hint(sres_sip_t *srs, int qtype, int protocol) |
457 | { |
458 | size_t i, j; |
459 | int match = 0; |
460 | uint16_t port = srs->srs_port; |
461 | |
462 | for (j = 0; sres_sip_tports[j].stp_number; j++) { |
463 | struct sres_sip_tport const *stp = &sres_sip_tports[j]; |
464 | int already = 0; |
465 | |
466 | if (protocol && stp->stp_number != protocol) |
467 | continue; |
468 | |
469 | /* Use only secure transports with SIPS */ |
470 | if (srs->srs_url->url_type == url_sips) { |
471 | if (!(stp->stp_number & TPPROTO_SECURE)) |
472 | continue; |
473 | } |
474 | |
475 | /* If transport is specified, use it. */ |
476 | if (srs->srs_transport && stp->stp_number != srs->srs_transport) |
477 | continue; |
478 | |
479 | for (i = 1; srs->srs_hints[i].hint_stp; i++) { |
480 | if (srs->srs_hints[i].hint_stp == stp && |
481 | srs->srs_hints[i].hint_qtype == qtype) { |
482 | match = 1, already = 1; |
483 | break; |
484 | } |
485 | assert(i <= 2 * N_TRANSPORTS)((void) sizeof ((i <= 2 * 20) ? 1 : 0), __extension__ ({ if (i <= 2 * 20) ; else __assert_fail ("i <= 2 * N_TRANSPORTS" , "sres_sip.c", 485, __extension__ __PRETTY_FUNCTION__); })); |
486 | } |
487 | |
488 | if (!already) { |
489 | srs->srs_hints[i].hint_stp = stp; |
490 | srs->srs_hints[i].hint_qtype = qtype; |
491 | srs->srs_hints[i].hint_port = port ? port : stp->stp_port; |
492 | } |
493 | } |
494 | |
495 | if (!match) { |
496 | /* XXX - hint did not match configured protocols */ |
497 | } |
498 | } |
499 | |
500 | /** Return protocol number for transport parameter in URI */ |
501 | static int |
502 | sres_sip_url_transport(url_t const *uri) |
503 | { |
504 | char parameter[64]; |
505 | isize_t len = 0; |
506 | size_t i; |
507 | |
508 | if (!uri) |
509 | return -1; |
510 | if (!uri->url_params) |
511 | return 0; |
512 | |
513 | len = url_param(uri->url_params, "transport", parameter, (sizeof parameter)); |
514 | if (len == 0) |
515 | return 0; |
516 | if (len >= sizeof parameter) |
517 | return -1; |
518 | |
519 | for (i = 0; *sres_sip_tports[i].stp_name; i++) { |
520 | if (su_casematch(parameter, sres_sip_tports[i].stp_name)) |
521 | return sres_sip_tports[i].stp_number; |
522 | } |
523 | |
524 | return -1; |
525 | } |
526 | |
527 | static char const * |
528 | sres_sip_transport_name(int number) |
529 | { |
530 | size_t i; |
531 | |
532 | for (i = 0; sres_sip_tports[i].stp_number; i++) { |
533 | if (number == sres_sip_tports[i].stp_number) |
534 | return sres_sip_tports[i].stp_name; |
535 | } |
536 | |
537 | return NULL((void*)0); |
538 | } |
539 | |
540 | /** Cancel resolver query */ |
541 | void |
542 | sres_sip_cancel_resolver(sres_sip_t *srs) |
543 | { |
544 | struct srs_step *step; |
545 | |
546 | if (!srs) |
547 | return; |
548 | |
549 | for (step = srs->srs_head; step; step = step->sp_next) { |
550 | sres_query_bind(step->sp_query, NULL((void*)0), NULL((void*)0)), step->sp_query = NULL((void*)0); |
551 | } |
552 | } |
553 | |
554 | #if 0 |
555 | |
556 | /** Graylist SRV records */ |
557 | static void |
558 | sres_sip_graylist(sres_sip_t *srs, |
559 | struct srs_step *step) |
560 | { |
561 | char const *target = step->sp_target, *proto = step->sp_proto; |
562 | unsigned prio = step->sp_priority, maxprio = prio; |
563 | |
564 | /* Don't know how to graylist but SRV records */ |
565 | if (step->sp_otype != sres_type_srv) |
566 | return; |
567 | |
568 | SU_DEBUG_5(("srs(%p): graylisting %s:%u;transport=%s\n", (void *) target, step->sp_port, proto))(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 568, "srs(%p): graylisting %s:%u;transport=%s\n" , (void *) target, step->sp_port, proto)) : (void)0); |
569 | |
570 | for (step = srs->srs_send; step; step = step->sp_next) |
571 | if (step->sp_otype == sres_type_srv && step->sp_priority > maxprio) |
572 | maxprio = step->sp_priority; |
573 | |
574 | for (step = srs->srs_done; step; step = step->sp_next) |
575 | if (step->sp_otype == sres_type_srv && step->sp_priority > maxprio) |
576 | maxprio = step->sp_priority; |
577 | |
578 | for (step = srs->srs_done; step; step = step->sp_next) { |
579 | int modified; |
580 | |
581 | if (step->sp_type != sres_type_srv || strcmp(proto, step->sp_proto)) |
582 | continue; |
583 | |
584 | /* modify the SRV record(s) corresponding to the latest A/AAAA record */ |
585 | modified = sres_set_cached_srv_priority( |
586 | srs->orq_agent->sa_resolver, |
587 | step->sp_target, |
588 | target, |
589 | step->sp_port, |
590 | srs->orq_agent->sa_graylist, |
591 | maxprio + 1); |
592 | |
593 | if (modified >= 0) |
594 | SU_DEBUG_3(("srs(%p): reduced priority of %d %s SRV records (increase value to %u)\n",(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 3 ? (_su_llog(sresolv_log, 3, "sres_sip.c" , (const char *)__func__, 596, "srs(%p): reduced priority of %d %s SRV records (increase value to %u)\n" , (void *)srs, modified, step->sp_target, maxprio + 1)) : ( void)0) |
595 | (void *)srs,(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 3 ? (_su_llog(sresolv_log, 3, "sres_sip.c" , (const char *)__func__, 596, "srs(%p): reduced priority of %d %s SRV records (increase value to %u)\n" , (void *)srs, modified, step->sp_target, maxprio + 1)) : ( void)0) |
596 | modified, step->sp_target, maxprio + 1))(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 3 ? (_su_llog(sresolv_log, 3, "sres_sip.c" , (const char *)__func__, 596, "srs(%p): reduced priority of %d %s SRV records (increase value to %u)\n" , (void *)srs, modified, step->sp_target, maxprio + 1)) : ( void)0); |
597 | else |
598 | SU_DEBUG_3(("srs(%p): failed to reduce %s SRV priority\n",(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 3 ? (_su_llog(sresolv_log, 3, "sres_sip.c" , (const char *)__func__, 600, "srs(%p): failed to reduce %s SRV priority\n" , (void *)srs, step->sp_target)) : (void)0) |
599 | (void *)srs,(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 3 ? (_su_llog(sresolv_log, 3, "sres_sip.c" , (const char *)__func__, 600, "srs(%p): failed to reduce %s SRV priority\n" , (void *)srs, step->sp_target)) : (void)0) |
600 | step->sp_target))(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 3 ? (_su_llog(sresolv_log, 3, "sres_sip.c" , (const char *)__func__, 600, "srs(%p): failed to reduce %s SRV priority\n" , (void *)srs, step->sp_target)) : (void)0); |
601 | } |
602 | } |
603 | #endif |
604 | |
605 | /** Take next step in resolving process. |
606 | * |
607 | * @retval 1 if there is more steps left |
608 | * @retval 0 if resolving process is complete |
609 | */ |
610 | int |
611 | sres_sip_next_step(sres_sip_t *srs) |
612 | { |
613 | if (srs == NULL((void*)0)) |
614 | return 0; |
615 | |
616 | for (;;) { |
617 | sres_sip_process(srs); /* Process answers */ |
618 | |
619 | if (sres_sip_is_waiting(srs)) |
620 | return 1; |
621 | |
622 | sres_sip_try_next_steps(srs); |
623 | |
624 | if (!sres_sip_send_steps(srs)) |
625 | break; |
626 | } |
627 | |
628 | if (sres_sip_is_waiting(srs)) |
629 | return 1; |
630 | |
631 | if (!srs->srs_complete) { |
632 | SU_DEBUG_5(("srs(%p): complete\n", (void *)srs))(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 632, "srs(%p): complete\n", (void * )srs)) : (void)0); |
633 | srs->srs_complete = 1; |
634 | } |
635 | |
636 | assert(*srs->srs_process == NULL)((void) sizeof ((*srs->srs_process == ((void*)0)) ? 1 : 0) , __extension__ ({ if (*srs->srs_process == ((void*)0)) ; else __assert_fail ("*srs->srs_process == NULL", "sres_sip.c", 636, __extension__ __PRETTY_FUNCTION__); })); |
637 | assert(!srs->srs_try_naptr && !srs->srs_try_srv && !srs->srs_try_a)((void) sizeof ((!srs->srs_try_naptr && !srs->srs_try_srv && !srs->srs_try_a) ? 1 : 0), __extension__ ({ if (!srs->srs_try_naptr && !srs->srs_try_srv && !srs->srs_try_a) ; else __assert_fail ("!srs->srs_try_naptr && !srs->srs_try_srv && !srs->srs_try_a" , "sres_sip.c", 637, __extension__ __PRETTY_FUNCTION__); })); |
638 | |
639 | return 0; |
640 | } |
641 | |
642 | static int |
643 | sres_sip_is_waiting(sres_sip_t const *srs) |
644 | { |
645 | return *srs->srs_process && (*srs->srs_process)->sp_query; |
646 | } |
647 | |
648 | static void |
649 | sres_sip_try_next_steps(sres_sip_t *srs) |
650 | { |
651 | if (*srs->srs_send == NULL((void*)0)) { |
652 | if (srs->srs_try_naptr) { |
653 | sres_sip_try_naptr_steps(srs); |
654 | } |
655 | else if (srs->srs_try_srv) { |
656 | sres_sip_try_srv_steps(srs); |
657 | } |
658 | else if (srs->srs_try_a) { |
659 | sres_sip_try_a_aaaa_steps(srs); |
660 | } |
661 | } |
662 | } |
663 | |
664 | /** Try target NAPTR. */ |
665 | static void |
666 | sres_sip_try_naptr_steps(sres_sip_t *srs) |
667 | { |
668 | struct srs_step *step; |
669 | |
670 | srs->srs_try_naptr = 0; |
671 | step = sres_sip_step_new(srs, sres_type_naptr, NULL((void*)0), srs->srs_target); |
672 | sres_sip_append_step(srs, step); |
673 | } |
674 | |
675 | /** If no NAPTR is found, try target SRVs. */ |
676 | static void |
677 | sres_sip_try_srv_steps(sres_sip_t *srs) |
678 | { |
679 | int i; |
680 | char const *target = srs->srs_target; |
681 | |
682 | srs->srs_try_srv = 0; |
683 | |
684 | for (i = 1; srs->srs_hints[i].hint_stp; i++) { |
685 | struct sres_sip_tport const *stp; |
686 | struct srs_step *step; |
687 | |
688 | stp = srs->srs_hints[i].hint_stp; |
689 | step = sres_sip_step_new(srs, sres_type_srv, stp->stp_prefix, target); |
690 | |
691 | if (step) { |
692 | step->sp_hint = i; |
693 | step->sp_prefer = i + 1; |
694 | step->sp_priority = 1; |
695 | step->sp_weight = 1; |
696 | sres_sip_append_step(srs, step); |
697 | } |
698 | } |
699 | } |
700 | |
701 | /** If not NAPTR or SRV was found, try target A/AAAAs. */ |
702 | static void |
703 | sres_sip_try_a_aaaa_steps(sres_sip_t *srs) |
704 | { |
705 | int i; |
706 | |
707 | srs->srs_try_a = 0; |
708 | |
709 | for (i = 1; srs->srs_hints[i].hint_stp; i++) { |
710 | struct srs_hint *hint = srs->srs_hints + i; |
711 | struct sres_sip_tport const *stp = hint->hint_stp; |
712 | struct srs_step *step; |
713 | |
714 | /* Consider only transport from uri parameter */ |
715 | if (!srs->srs_transport && |
716 | /* ...or default transports for this URI type */ |
717 | stp->stp_type != srs->srs_url->url_type) |
718 | continue; |
719 | |
720 | step = sres_sip_step_new(srs, hint->hint_qtype, NULL((void*)0), srs->srs_target); |
721 | |
722 | if (step) { |
723 | step->sp_hint = i; |
724 | step->sp_prefer = 2; |
725 | step->sp_priority = i; |
726 | step->sp_port = srs->srs_port ? srs->srs_port : stp->stp_port; |
727 | sres_sip_append_step(srs, step); |
728 | } |
729 | } |
730 | } |
731 | |
732 | /** Send queries or lookup from cache. |
733 | * |
734 | * Return true if got data to process. |
735 | */ |
736 | static int |
737 | sres_sip_send_steps(sres_sip_t *srs) |
738 | { |
739 | int process = 0; |
740 | |
741 | /* New queries to send */ |
742 | while (*srs->srs_send) { |
743 | struct srs_step *step = *srs->srs_send, *step2; |
744 | uint16_t type = step->sp_type; |
745 | char const *domain = step->sp_target; |
746 | sres_record_t **answers; |
747 | int parallel = 0; |
748 | |
749 | srs->srs_send = &step->sp_next; |
750 | |
751 | if (step->sp_status != STEP_QUEUED) { |
752 | assert(step->sp_already != step)((void) sizeof ((step->sp_already != step) ? 1 : 0), __extension__ ({ if (step->sp_already != step) ; else __assert_fail ("step->sp_already != step" , "sres_sip.c", 752, __extension__ __PRETTY_FUNCTION__); })); |
753 | continue; |
754 | } |
755 | |
756 | assert(step->sp_already == step)((void) sizeof ((step->sp_already == step) ? 1 : 0), __extension__ ({ if (step->sp_already == step) ; else __assert_fail ("step->sp_already == step" , "sres_sip.c", 756, __extension__ __PRETTY_FUNCTION__); })); |
757 | |
758 | answers = sres_cached_answers(srs->srs_resolver, type, domain); |
759 | |
760 | for (step2 = step; step2; step2 = step2->sp_next) { |
761 | if (step2->sp_already == step) |
762 | step2->sp_status = answers ? STEP_CACHED : STEP_SENT; |
763 | } |
764 | |
765 | |
766 | SU_DEBUG_5(("srs(%p): query %s %s%s\n",(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 768, "srs(%p): query %s %s%s\n", (void *)srs, sres_record_type(type, ((void*)0)), domain, answers ? " (cached)" : "")) : (void)0) |
767 | (void *)srs, sres_record_type(type, NULL), domain,(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 768, "srs(%p): query %s %s%s\n", (void *)srs, sres_record_type(type, ((void*)0)), domain, answers ? " (cached)" : "")) : (void)0) |
768 | answers ? " (cached)" : ""))(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 768, "srs(%p): query %s %s%s\n", (void *)srs, sres_record_type(type, ((void*)0)), domain, answers ? " (cached)" : "")) : (void)0); |
769 | |
770 | if (answers) |
771 | ; |
772 | else if (srs->srs_blocking) { |
773 | sres_blocking_query(srs->srs_resolver, type, domain, 0, &answers); |
774 | } |
775 | else { |
776 | step->sp_query = sres_query(srs->srs_resolver, |
777 | sres_sip_answer, step, |
778 | type, domain); |
779 | if (step->sp_query) { |
780 | /* Query all self-generated SRV records at the same time */ |
781 | parallel = step->sp_trace == NULL((void*)0) && type == sres_type_srv; |
782 | if (!parallel) |
783 | break; |
784 | continue; |
785 | } |
786 | } |
787 | |
788 | sres_sip_answer(step, NULL((void*)0), answers); |
789 | return process = 1; |
790 | } |
791 | |
792 | return process = 0; |
793 | } |
794 | |
795 | static void |
796 | sres_sip_answer(struct srs_step *step, |
797 | sres_query_t *q, |
798 | sres_record_t *answers[]) |
799 | { |
800 | sres_sip_t *srs = step->sp_srs; |
801 | struct srs_step *step2; |
802 | int status = sres_sip_status_of_answers(answers, step->sp_type); |
803 | |
804 | SU_DEBUG_5(("srs(%p): %s %s (answers=%u) for %s %s\n",(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 809, "srs(%p): %s %s (answers=%u) for %s %s\n" , (void *)srs, step->sp_status == STEP_SENT ? "received" : "cached", sres_record_status(status, ((void*)0)), sres_sip_count_answers (answers, step->sp_type), sres_record_type(step->sp_type , ((void*)0)), step->sp_target)) : (void)0) |
805 | (void *)srs,(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 809, "srs(%p): %s %s (answers=%u) for %s %s\n" , (void *)srs, step->sp_status == STEP_SENT ? "received" : "cached", sres_record_status(status, ((void*)0)), sres_sip_count_answers (answers, step->sp_type), sres_record_type(step->sp_type , ((void*)0)), step->sp_target)) : (void)0) |
806 | step->sp_status == STEP_SENT ? "received" : "cached",(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 809, "srs(%p): %s %s (answers=%u) for %s %s\n" , (void *)srs, step->sp_status == STEP_SENT ? "received" : "cached", sres_record_status(status, ((void*)0)), sres_sip_count_answers (answers, step->sp_type), sres_record_type(step->sp_type , ((void*)0)), step->sp_target)) : (void)0) |
807 | sres_record_status(status, NULL),(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 809, "srs(%p): %s %s (answers=%u) for %s %s\n" , (void *)srs, step->sp_status == STEP_SENT ? "received" : "cached", sres_record_status(status, ((void*)0)), sres_sip_count_answers (answers, step->sp_type), sres_record_type(step->sp_type , ((void*)0)), step->sp_target)) : (void)0) |
808 | sres_sip_count_answers(answers, step->sp_type),(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 809, "srs(%p): %s %s (answers=%u) for %s %s\n" , (void *)srs, step->sp_status == STEP_SENT ? "received" : "cached", sres_record_status(status, ((void*)0)), sres_sip_count_answers (answers, step->sp_type), sres_record_type(step->sp_type , ((void*)0)), step->sp_target)) : (void)0) |
809 | sres_record_type(step->sp_type, NULL), step->sp_target))(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 809, "srs(%p): %s %s (answers=%u) for %s %s\n" , (void *)srs, step->sp_status == STEP_SENT ? "received" : "cached", sres_record_status(status, ((void*)0)), sres_sip_count_answers (answers, step->sp_type), sres_record_type(step->sp_type , ((void*)0)), step->sp_target)) : (void)0); |
810 | |
811 | sres_sip_log_answers(srs, step, answers); |
812 | |
813 | assert(step->sp_already == step)((void) sizeof ((step->sp_already == step) ? 1 : 0), __extension__ ({ if (step->sp_already == step) ; else __assert_fail ("step->sp_already == step" , "sres_sip.c", 813, __extension__ __PRETTY_FUNCTION__); })); |
814 | assert(step->sp_query == q)((void) sizeof ((step->sp_query == q) ? 1 : 0), __extension__ ({ if (step->sp_query == q) ; else __assert_fail ("step->sp_query == q" , "sres_sip.c", 814, __extension__ __PRETTY_FUNCTION__); })); step->sp_query = NULL((void*)0); |
815 | assert(step->sp_status == STEP_SENT ||((void) sizeof ((step->sp_status == STEP_SENT || step-> sp_status == STEP_CACHED) ? 1 : 0), __extension__ ({ if (step ->sp_status == STEP_SENT || step->sp_status == STEP_CACHED ) ; else __assert_fail ("step->sp_status == STEP_SENT || step->sp_status == STEP_CACHED" , "sres_sip.c", 816, __extension__ __PRETTY_FUNCTION__); })) |
816 | step->sp_status == STEP_CACHED)((void) sizeof ((step->sp_status == STEP_SENT || step-> sp_status == STEP_CACHED) ? 1 : 0), __extension__ ({ if (step ->sp_status == STEP_SENT || step->sp_status == STEP_CACHED ) ; else __assert_fail ("step->sp_status == STEP_SENT || step->sp_status == STEP_CACHED" , "sres_sip.c", 816, __extension__ __PRETTY_FUNCTION__); })); |
817 | |
818 | step->sp_results = answers; |
819 | step->sp_status = status; |
820 | |
821 | /* Check if answer is valid for another query, too */ |
822 | for (step2 = step->sp_next; step2; step2 = step2->sp_next) { |
823 | if (step2->sp_already == step) { |
824 | step2->sp_results = answers; |
825 | step2->sp_status = status; |
826 | } |
827 | } |
828 | |
829 | if (!sres_sip_next_step(srs)) { |
830 | sres_sip_return_results(srs, 1); |
831 | } |
832 | else if (q && *srs->srs_next) { |
833 | sres_sip_return_results(srs, 0); |
834 | } |
835 | } |
836 | |
837 | static int |
838 | sres_sip_status_of_answers(sres_record_t *answers[], uint16_t type) |
839 | { |
840 | int i; |
841 | |
842 | if (answers == NULL((void*)0)) |
843 | return SRES_NETWORK_ERR; |
844 | |
845 | for (i = 0; answers[i]; i++) { |
846 | if (answers[i]->sr_record->r_type == type) { |
847 | return answers[i]->sr_record->r_status; |
848 | } |
849 | } |
850 | |
851 | return SRES_RECORD_ERR; |
852 | } |
853 | |
854 | static int |
855 | sres_sip_count_answers(sres_record_t *answers[], uint16_t type) |
856 | { |
857 | int n; |
858 | |
859 | for (n = 0; answers && answers[n]; n++) { |
860 | if (type != answers[n]->sr_record->r_type || |
861 | answers[n]->sr_record->r_status != 0) |
862 | break; |
863 | } |
864 | |
865 | return n; |
866 | } |
867 | |
868 | static void |
869 | sres_sip_log_answers(sres_sip_t *srs, |
870 | struct srs_step *step, |
871 | sres_record_t *answers[]) |
872 | { |
873 | char const *previous; |
874 | int i; |
875 | |
876 | if (answers == NULL((void*)0)) |
877 | return; |
878 | if (SU_LOGsresolv_log->log_level < 5) |
879 | return; |
880 | |
881 | previous = step->sp_target; |
882 | |
883 | for (i = 0; answers[i]; i++) { |
884 | sres_record_t *sr = answers[i]; |
885 | int type = sr->sr_record->r_type; |
886 | char const *domain = sr->sr_record->r_name; |
887 | char addr[SU_ADDRSIZE(48)]; |
888 | |
889 | if (sr->sr_record->r_status) |
890 | continue; |
891 | |
892 | if (su_casematch(previous, domain)) |
893 | domain = ""; |
894 | else |
895 | previous = domain; |
896 | |
897 | if (type == sres_type_a) { |
898 | sres_a_record_t const *a = sr->sr_a; |
899 | su_inet_ntopinet_ntop(AF_INET2, &a->a_addr, addr, sizeof(addr)); |
900 | SU_DEBUG_5(("srs(%p): %s IN A %s\n", (void *)srs, domain, addr))(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 900, "srs(%p): %s IN A %s\n", (void *)srs, domain, addr)) : (void)0); |
901 | } |
902 | else if (type == sres_type_cname) { |
903 | char const *cname = sr->sr_cname->cn_cname; |
904 | SU_DEBUG_5(("srs(%p): %s IN CNAME %s\n", (void *)srs, domain, cname))(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 904, "srs(%p): %s IN CNAME %s\n", ( void *)srs, domain, cname)) : (void)0); |
905 | } |
906 | #if SU_HAVE_IN61 |
907 | else if (type == sres_type_aaaa) { |
908 | sres_aaaa_record_t const *aaaa = sr->sr_aaaa; |
909 | su_inet_ntopinet_ntop(AF_INET610, &aaaa->aaaa_addr, addr, sizeof(addr)); |
910 | SU_DEBUG_5(("srs(%p): %s IN AAAA %s\n", (void *)srs, domain, addr))(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 910, "srs(%p): %s IN AAAA %s\n", (void *)srs, domain, addr)) : (void)0); |
911 | } |
912 | #endif |
913 | else if (type == sres_type_naptr) { |
914 | sres_naptr_record_t const *na = sr->sr_naptr; |
915 | SU_DEBUG_5(("srs(%p): %s IN NAPTR %u %u \"%s\" \"%s\" \"%s\" %s\n",(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 920, "srs(%p): %s IN NAPTR %u %u \"%s\" \"%s\" \"%s\" %s\n" , (void *)srs, domain, na->na_order, na->na_prefer, na-> na_flags, na->na_services, na->na_regexp, na->na_replace )) : (void)0) |
916 | (void *)srs,(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 920, "srs(%p): %s IN NAPTR %u %u \"%s\" \"%s\" \"%s\" %s\n" , (void *)srs, domain, na->na_order, na->na_prefer, na-> na_flags, na->na_services, na->na_regexp, na->na_replace )) : (void)0) |
917 | domain,(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 920, "srs(%p): %s IN NAPTR %u %u \"%s\" \"%s\" \"%s\" %s\n" , (void *)srs, domain, na->na_order, na->na_prefer, na-> na_flags, na->na_services, na->na_regexp, na->na_replace )) : (void)0) |
918 | na->na_order, na->na_prefer,(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 920, "srs(%p): %s IN NAPTR %u %u \"%s\" \"%s\" \"%s\" %s\n" , (void *)srs, domain, na->na_order, na->na_prefer, na-> na_flags, na->na_services, na->na_regexp, na->na_replace )) : (void)0) |
919 | na->na_flags, na->na_services,(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 920, "srs(%p): %s IN NAPTR %u %u \"%s\" \"%s\" \"%s\" %s\n" , (void *)srs, domain, na->na_order, na->na_prefer, na-> na_flags, na->na_services, na->na_regexp, na->na_replace )) : (void)0) |
920 | na->na_regexp, na->na_replace))(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 920, "srs(%p): %s IN NAPTR %u %u \"%s\" \"%s\" \"%s\" %s\n" , (void *)srs, domain, na->na_order, na->na_prefer, na-> na_flags, na->na_services, na->na_regexp, na->na_replace )) : (void)0); |
921 | } |
922 | else if (type == sres_type_srv) { |
923 | sres_srv_record_t const *srv = sr->sr_srv; |
924 | SU_DEBUG_5(("srs(%p): %s IN SRV %u %u %u %s\n",(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 928, "srs(%p): %s IN SRV %u %u %u %s\n" , (void *)srs, domain, (unsigned)srv->srv_priority, (unsigned )srv->srv_weight, srv->srv_port, srv->srv_target)) : (void)0) |
925 | (void *)srs,(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 928, "srs(%p): %s IN SRV %u %u %u %s\n" , (void *)srs, domain, (unsigned)srv->srv_priority, (unsigned )srv->srv_weight, srv->srv_port, srv->srv_target)) : (void)0) |
926 | domain,(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 928, "srs(%p): %s IN SRV %u %u %u %s\n" , (void *)srs, domain, (unsigned)srv->srv_priority, (unsigned )srv->srv_weight, srv->srv_port, srv->srv_target)) : (void)0) |
927 | (unsigned)srv->srv_priority, (unsigned)srv->srv_weight,(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 928, "srs(%p): %s IN SRV %u %u %u %s\n" , (void *)srs, domain, (unsigned)srv->srv_priority, (unsigned )srv->srv_weight, srv->srv_port, srv->srv_target)) : (void)0) |
928 | srv->srv_port, srv->srv_target))(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 928, "srs(%p): %s IN SRV %u %u %u %s\n" , (void *)srs, domain, (unsigned)srv->srv_priority, (unsigned )srv->srv_weight, srv->srv_port, srv->srv_target)) : (void)0); |
929 | } |
930 | else { |
931 | /* Ignore */ |
932 | } |
933 | } |
934 | } |
935 | |
936 | |
937 | |
938 | |
939 | /** Return error response */ |
940 | static void |
941 | sres_sip_return_results(sres_sip_t *srs, int final) |
942 | { |
943 | if (final && srs->srs_results == NULL((void*)0) && !srs->srs_error) { |
944 | /* Get best error */ |
945 | struct srs_step *step; |
946 | |
947 | for (step = srs->srs_head; step; step = step->sp_next) { |
948 | switch (step->sp_status) { |
949 | case SRES_NAME_ERR: |
950 | if (su_casematch(step->sp_target, srs->srs_target)) |
951 | srs->srs_error = SRES_SIP_ERR_NO_NAME; |
952 | break; |
953 | case SRES_OK: |
954 | case SRES_RECORD_ERR: |
955 | /* Something was found */ |
956 | srs->srs_error = SRES_SIP_ERR_NO_DATA; |
957 | break; |
958 | case SRES_AUTH_ERR: |
959 | case SRES_FORMAT_ERR: |
960 | srs->srs_error = SRES_SIP_ERR_FAIL; |
961 | break; |
962 | case SRES_SERVER_ERR: |
963 | case SRES_TIMEOUT_ERR: |
964 | case SRES_NETWORK_ERR: |
965 | srs->srs_error = SRES_SIP_ERR_AGAIN; |
966 | break; |
967 | } |
968 | if (srs->srs_error) |
969 | break; |
970 | } |
971 | |
972 | if (!srs->srs_error) |
973 | srs->srs_error = SRES_SIP_ERR_FAIL; |
974 | } |
975 | |
976 | if (srs->srs_callback) { |
977 | sres_sip_notify_f *callback = srs->srs_callback; |
978 | sres_sip_magic_t *magic = srs->srs_magic; |
979 | |
980 | if (final) |
981 | srs->srs_callback = NULL((void*)0), srs->srs_magic = NULL((void*)0); |
982 | |
983 | callback(magic, srs, final); |
984 | } |
985 | } |
986 | |
987 | static int |
988 | sres_sip_process(sres_sip_t *srs) |
989 | { |
990 | while (*srs->srs_process) { |
991 | struct srs_step *step = *srs->srs_process; |
992 | |
993 | if (step->sp_query) |
994 | return 1; |
995 | |
996 | if (step->sp_status < 0) |
997 | break; |
998 | |
999 | if (srs->srs_process != srs->srs_send) |
1000 | srs->srs_process = &step->sp_next; |
1001 | else |
1002 | srs->srs_send = srs->srs_process = &step->sp_next; |
1003 | |
1004 | if (step->sp_status == SRES_RECORD_ERR) { |
1005 | sres_sip_process_cname(srs, step, step->sp_results); |
1006 | continue; |
1007 | } |
1008 | |
1009 | if (step->sp_status) |
1010 | continue; |
1011 | |
1012 | SU_DEBUG_5(("srs(%p): process %s %s record%s\n",(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 1015, "srs(%p): process %s %s record%s\n" , (void *)srs, sres_record_type(step->sp_type, ((void*)0)) , step->sp_target, step->sp_already != step ? " (again)" : "")) : (void)0) |
1013 | (void *)srs,(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 1015, "srs(%p): process %s %s record%s\n" , (void *)srs, sres_record_type(step->sp_type, ((void*)0)) , step->sp_target, step->sp_already != step ? " (again)" : "")) : (void)0) |
1014 | sres_record_type(step->sp_type, NULL), step->sp_target,(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 1015, "srs(%p): process %s %s record%s\n" , (void *)srs, sres_record_type(step->sp_type, ((void*)0)) , step->sp_target, step->sp_already != step ? " (again)" : "")) : (void)0) |
1015 | step->sp_already != step ? " (again)" : ""))(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 1015, "srs(%p): process %s %s record%s\n" , (void *)srs, sres_record_type(step->sp_type, ((void*)0)) , step->sp_target, step->sp_already != step ? " (again)" : "")) : (void)0); |
1016 | |
1017 | switch (step->sp_type) { |
1018 | case sres_type_naptr: |
1019 | sres_sip_process_naptr(srs, step, step->sp_results); |
1020 | break; |
1021 | case sres_type_srv: |
1022 | sres_sip_process_srv(srs, step, step->sp_results); |
1023 | break; |
1024 | #if SU_HAVE_IN61 |
1025 | case sres_type_aaaa: |
1026 | sres_sip_process_aaaa(srs, step, step->sp_results); |
1027 | break; |
1028 | #endif |
1029 | case sres_type_a: |
1030 | sres_sip_process_a(srs, step, step->sp_results); |
1031 | break; |
1032 | |
1033 | default: |
1034 | assert(!"unknown query type")((void) sizeof ((!"unknown query type") ? 1 : 0), __extension__ ({ if (!"unknown query type") ; else __assert_fail ("!\"unknown query type\"" , "sres_sip.c", 1034, __extension__ __PRETTY_FUNCTION__); })); |
1035 | } |
1036 | } |
1037 | |
1038 | return 0; |
1039 | } |
1040 | |
1041 | |
1042 | static struct srs_step * |
1043 | sres_sip_step_new(sres_sip_t *srs, |
1044 | int type, |
1045 | char const *prefix, |
1046 | char const *domain) |
1047 | { |
1048 | struct srs_step *step, *step0; |
1049 | size_t plen = prefix ? strlen(prefix) : 0; |
1050 | size_t extra = 0; |
1051 | |
1052 | for (step0 = srs->srs_head; step0; step0 = step0->sp_next) { |
1053 | if (step0->sp_type == type && |
1054 | su_casenmatch(prefix, step0->sp_target, plen) && |
1055 | su_casematch(step0->sp_target + plen, domain)) |
1056 | break; |
1057 | } |
1058 | |
1059 | if (prefix && !step0) |
1060 | extra = plen + strlen(domain) + 1; |
1061 | |
1062 | step = su_zalloc(srs->srs_home, (sizeof *step) + extra); |
1063 | |
1064 | if (step) { |
1065 | step->sp_srs = srs; |
1066 | step->sp_type = type; |
1067 | step->sp_status = STEP_NEW; |
1068 | |
1069 | if (step0) { |
1070 | step->sp_already = step0; |
1071 | step->sp_results = step0->sp_results; |
1072 | step->sp_target = step0->sp_target; |
1073 | } |
1074 | else { |
1075 | step->sp_already = step; |
1076 | |
1077 | if (prefix) { |
1078 | char *target = (char *)(step + 1); |
1079 | step->sp_target = memcpy(target, prefix, plen); |
1080 | strcpy(target + plen, domain); |
1081 | } |
1082 | else { |
1083 | step->sp_target = domain; |
1084 | } |
1085 | } |
1086 | } |
1087 | |
1088 | return step; |
1089 | } |
1090 | |
1091 | |
1092 | /** Append a step to queue */ |
1093 | static void |
1094 | sres_sip_append_step(sres_sip_t *srs, |
1095 | struct srs_step *step) |
1096 | { |
1097 | if (step == NULL((void*)0)) |
1098 | return; |
1099 | |
1100 | assert(step->sp_status == STEP_NEW)((void) sizeof ((step->sp_status == STEP_NEW) ? 1 : 0), __extension__ ({ if (step->sp_status == STEP_NEW) ; else __assert_fail ( "step->sp_status == STEP_NEW", "sres_sip.c", 1100, __extension__ __PRETTY_FUNCTION__); })); |
1101 | |
1102 | *srs->srs_queue = step, srs->srs_queue = &step->sp_next; |
1103 | |
1104 | if (step->sp_already == step) { |
1105 | step->sp_status = STEP_QUEUED; |
1106 | } |
1107 | else { |
1108 | step->sp_status = step->sp_already->sp_status; |
1109 | step->sp_results = step->sp_already->sp_results; |
1110 | } |
1111 | } |
1112 | |
1113 | /** Insert a step to queue. |
1114 | * |
1115 | * Sort by 1) order 2) priority/preference 3) weight. |
1116 | */ |
1117 | static void |
1118 | sres_sip_insert_step(sres_sip_t *srs, |
1119 | struct srs_step *step) |
1120 | { |
1121 | struct srs_step *already, *step2, **insert, **at, **next; |
1122 | struct srs_hint *hint = &srs->srs_hints[step->sp_hint]; |
1123 | struct sres_sip_tport const *stp = hint->hint_stp; |
1124 | int weight = 0, N = 0, by; |
1125 | |
1126 | /* Currently, inserted steps are results from CNAME or SRV. |
1127 | They have hint at this point */ |
1128 | assert(step->sp_hint)((void) sizeof ((step->sp_hint) ? 1 : 0), __extension__ ({ if (step->sp_hint) ; else __assert_fail ("step->sp_hint" , "sres_sip.c", 1128, __extension__ __PRETTY_FUNCTION__); })); |
1129 | |
1130 | step->sp_srs = srs; |
1131 | |
1132 | insert = srs->srs_send; |
1133 | |
1134 | for (at = insert; *at; at = next) { |
1135 | next = &(*at)->sp_next; |
1136 | |
1137 | if (step->sp_prefer < (*at)->sp_prefer) { |
1138 | break; |
1139 | } |
1140 | if (step->sp_prefer > (*at)->sp_prefer) { |
1141 | insert = next, weight = 0, N = 0; |
1142 | continue; |
1143 | } |
1144 | if (step->sp_priority < (*at)->sp_priority) { |
1145 | break; |
1146 | } |
1147 | if (step->sp_priority > (*at)->sp_priority) { |
1148 | insert = next, weight = 0, N = 0; |
1149 | continue; |
1150 | } |
1151 | |
1152 | weight += (*at)->sp_weight, N++; |
1153 | } |
1154 | |
1155 | if (step->sp_weight) |
1156 | weight += step->sp_weight; |
1157 | else |
1158 | insert = at; |
1159 | |
1160 | if (insert != at) |
1161 | by = su_randint(0, weight - 1); |
1162 | else |
1163 | by = weight; |
1164 | |
1165 | SU_DEBUG_5(("srs(%p): %s %s query for %s;transport=%s (N=%u %d/%d)\n",(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 1170, "srs(%p): %s %s query for %s;transport=%s (N=%u %d/%d)\n" , (void *)srs, insert != at ? "inserting" : "appending", sres_record_type (step->sp_type, ((void*)0)), step->sp_target, stp->stp_name , N, by, weight)) : (void)0) |
1166 | (void *)srs,(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 1170, "srs(%p): %s %s query for %s;transport=%s (N=%u %d/%d)\n" , (void *)srs, insert != at ? "inserting" : "appending", sres_record_type (step->sp_type, ((void*)0)), step->sp_target, stp->stp_name , N, by, weight)) : (void)0) |
1167 | insert != at ? "inserting" : "appending",(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 1170, "srs(%p): %s %s query for %s;transport=%s (N=%u %d/%d)\n" , (void *)srs, insert != at ? "inserting" : "appending", sres_record_type (step->sp_type, ((void*)0)), step->sp_target, stp->stp_name , N, by, weight)) : (void)0) |
1168 | sres_record_type(step->sp_type, NULL), step->sp_target,(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 1170, "srs(%p): %s %s query for %s;transport=%s (N=%u %d/%d)\n" , (void *)srs, insert != at ? "inserting" : "appending", sres_record_type (step->sp_type, ((void*)0)), step->sp_target, stp->stp_name , N, by, weight)) : (void)0) |
1169 | stp->stp_name,(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 1170, "srs(%p): %s %s query for %s;transport=%s (N=%u %d/%d)\n" , (void *)srs, insert != at ? "inserting" : "appending", sres_record_type (step->sp_type, ((void*)0)), step->sp_target, stp->stp_name , N, by, weight)) : (void)0) |
1170 | N, by, weight))(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 1170, "srs(%p): %s %s query for %s;transport=%s (N=%u %d/%d)\n" , (void *)srs, insert != at ? "inserting" : "appending", sres_record_type (step->sp_type, ((void*)0)), step->sp_target, stp->stp_name , N, by, weight)) : (void)0); |
1171 | |
1172 | if (insert != at) { |
1173 | for (;by > step->sp_weight; insert = &(*insert)->sp_next) { |
1174 | assert(*insert)((void) sizeof ((*insert) ? 1 : 0), __extension__ ({ if (*insert ) ; else __assert_fail ("*insert", "sres_sip.c", 1174, __extension__ __PRETTY_FUNCTION__); })); assert((*insert)->sp_prefer == step->sp_prefer)((void) sizeof (((*insert)->sp_prefer == step->sp_prefer ) ? 1 : 0), __extension__ ({ if ((*insert)->sp_prefer == step ->sp_prefer) ; else __assert_fail ("(*insert)->sp_prefer == step->sp_prefer" , "sres_sip.c", 1174, __extension__ __PRETTY_FUNCTION__); })); |
1175 | assert((*insert)->sp_priority == step->sp_priority)((void) sizeof (((*insert)->sp_priority == step->sp_priority ) ? 1 : 0), __extension__ ({ if ((*insert)->sp_priority == step->sp_priority) ; else __assert_fail ("(*insert)->sp_priority == step->sp_priority" , "sres_sip.c", 1175, __extension__ __PRETTY_FUNCTION__); })); |
1176 | by -= (*insert)->sp_weight; |
1177 | } |
1178 | } |
1179 | |
1180 | step->sp_next = *insert, *insert = step; |
1181 | if (insert == srs->srs_queue) |
1182 | srs->srs_queue = &step->sp_next; |
1183 | |
1184 | step->sp_status = STEP_QUEUED; |
1185 | |
1186 | if (step->sp_already == step) |
1187 | return; |
1188 | |
1189 | /* Check if sp_already is after step */ |
1190 | for (already = step->sp_next; already; already = already->sp_next) { |
1191 | if (already == step->sp_already) |
1192 | break; |
1193 | } |
1194 | |
1195 | if (already) { |
1196 | assert(already->sp_status == STEP_QUEUED)((void) sizeof ((already->sp_status == STEP_QUEUED) ? 1 : 0 ), __extension__ ({ if (already->sp_status == STEP_QUEUED) ; else __assert_fail ("already->sp_status == STEP_QUEUED" , "sres_sip.c", 1196, __extension__ __PRETTY_FUNCTION__); })); |
1197 | step->sp_already = step; |
1198 | for (step2 = step->sp_next; step2; step2 = step2->sp_next) { |
1199 | if (step2->sp_already == already) |
1200 | step2->sp_already = step; |
1201 | } |
1202 | } |
1203 | else { |
1204 | step->sp_status = step->sp_already->sp_status; |
1205 | step->sp_results = step->sp_already->sp_results; |
1206 | } |
1207 | } |
1208 | |
1209 | /* Process NAPTR records */ |
1210 | static void |
1211 | sres_sip_process_naptr(sres_sip_t *srs, |
1212 | struct srs_step *step, |
1213 | sres_record_t *answers[]) |
1214 | { |
1215 | int i, j, order = -1, found = 0; |
1216 | |
1217 | assert(answers)((void) sizeof ((answers) ? 1 : 0), __extension__ ({ if (answers ) ; else __assert_fail ("answers", "sres_sip.c", 1217, __extension__ __PRETTY_FUNCTION__); })); |
1218 | |
1219 | /* Sort NAPTR first by order then by preference */ |
1220 | /* sres_sort_answers() sorts with flags etc. too */ |
1221 | sres_sip_sort_naptr(answers); |
1222 | |
1223 | for (i = 0; answers[i]; i++) { |
1224 | sres_naptr_record_t const *na = answers[i]->sr_naptr; |
1225 | struct sres_sip_tport const *stp; |
1226 | int supported = 0; |
1227 | |
1228 | if (na->na_record->r_status) |
1229 | continue; |
1230 | if (na->na_record->r_type != sres_type_naptr) |
1231 | continue; |
1232 | |
1233 | /* RFC 2915 p 4: |
1234 | * Order |
1235 | * A 16-bit unsigned integer specifying the order in which the |
1236 | * NAPTR records MUST be processed to ensure the correct ordering |
1237 | * of rules. Low numbers are processed before high numbers, and |
1238 | * once a NAPTR is found whose rule "matches" the target, the |
1239 | * client MUST NOT consider any NAPTRs with a higher value for |
1240 | * order (except as noted below for the Flags field). |
1241 | */ |
1242 | if (order >= 0 && order != na->na_order) |
1243 | break; |
1244 | |
1245 | /* RFC3263 p. 6: |
1246 | First, a client resolving a SIPS URI MUST discard any services that |
1247 | do not contain "SIPS" as the protocol in the service field. The |
1248 | converse is not true, however. A client resolving a SIP URI SHOULD |
1249 | retain records with "SIPS" as the protocol, if the client supports |
1250 | TLS. |
1251 | */ |
1252 | if (su_casenmatch(na->na_services, "SIPS+", 5) || |
1253 | su_casenmatch(na->na_services, "SIP+", 4)) |
1254 | /* Use NAPTR results, don't try extra SRV/A/AAAA records */ |
1255 | srs->srs_try_srv = 0, srs->srs_try_a = 0, found = 1; |
1256 | else |
1257 | continue; /* Not a SIP/SIPS service */ |
1258 | |
1259 | /* Check if we have a transport matching with service */ |
1260 | for (j = 1; (stp = srs->srs_hints[j].hint_stp); j++) { |
1261 | /* |
1262 | * Syntax of services is actually more complicated |
1263 | * but comparing the values in the transport list |
1264 | * match with those values that make any sense |
1265 | */ |
1266 | if (su_casematch(na->na_services, stp->stp_service)) { |
1267 | /* We found matching NAPTR */ |
1268 | order = na->na_order; |
1269 | supported = 1; |
1270 | sres_sip_step_by_naptr(srs, step, j, na); |
1271 | } |
1272 | } |
1273 | |
1274 | SU_DEBUG_5(("srs(%p): %s IN NAPTR %u %u \"%s\" \"%s\" \"%s\" %s%s\n",(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 1280, "srs(%p): %s IN NAPTR %u %u \"%s\" \"%s\" \"%s\" %s%s\n" , (void *)srs, na->na_record->r_name, na->na_order, na ->na_prefer, na->na_flags, na->na_services, na->na_regexp , na->na_replace, supported ? "" : " (not supported)")) : ( void)0) |
1275 | (void *)srs,(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 1280, "srs(%p): %s IN NAPTR %u %u \"%s\" \"%s\" \"%s\" %s%s\n" , (void *)srs, na->na_record->r_name, na->na_order, na ->na_prefer, na->na_flags, na->na_services, na->na_regexp , na->na_replace, supported ? "" : " (not supported)")) : ( void)0) |
1276 | na->na_record->r_name,(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 1280, "srs(%p): %s IN NAPTR %u %u \"%s\" \"%s\" \"%s\" %s%s\n" , (void *)srs, na->na_record->r_name, na->na_order, na ->na_prefer, na->na_flags, na->na_services, na->na_regexp , na->na_replace, supported ? "" : " (not supported)")) : ( void)0) |
1277 | na->na_order, na->na_prefer,(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 1280, "srs(%p): %s IN NAPTR %u %u \"%s\" \"%s\" \"%s\" %s%s\n" , (void *)srs, na->na_record->r_name, na->na_order, na ->na_prefer, na->na_flags, na->na_services, na->na_regexp , na->na_replace, supported ? "" : " (not supported)")) : ( void)0) |
1278 | na->na_flags, na->na_services,(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 1280, "srs(%p): %s IN NAPTR %u %u \"%s\" \"%s\" \"%s\" %s%s\n" , (void *)srs, na->na_record->r_name, na->na_order, na ->na_prefer, na->na_flags, na->na_services, na->na_regexp , na->na_replace, supported ? "" : " (not supported)")) : ( void)0) |
1279 | na->na_regexp, na->na_replace,(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 1280, "srs(%p): %s IN NAPTR %u %u \"%s\" \"%s\" \"%s\" %s%s\n" , (void *)srs, na->na_record->r_name, na->na_order, na ->na_prefer, na->na_flags, na->na_services, na->na_regexp , na->na_replace, supported ? "" : " (not supported)")) : ( void)0) |
1280 | supported ? "" : " (not supported)"))(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 1280, "srs(%p): %s IN NAPTR %u %u \"%s\" \"%s\" \"%s\" %s%s\n" , (void *)srs, na->na_record->r_name, na->na_order, na ->na_prefer, na->na_flags, na->na_services, na->na_regexp , na->na_replace, supported ? "" : " (not supported)")) : ( void)0); |
1281 | } |
1282 | |
1283 | if (found && order < 0) |
1284 | /* There was a SIP/SIPS natpr, but it has no matching hints */ |
1285 | srs->srs_error = SRES_SIP_ERR_NO_TPORT; |
1286 | } |
1287 | |
1288 | static void |
1289 | sres_sip_sort_naptr(sres_record_t *answers[]) |
1290 | { |
1291 | int i, j; |
1292 | |
1293 | for (i = 0; answers[i]; i++) { |
1294 | sres_naptr_record_t const *na = answers[i]->sr_naptr; |
1295 | |
1296 | if (na->na_record->r_type != sres_type_naptr) |
1297 | break; |
1298 | |
1299 | for (j = 0; j < i; j++) { |
1300 | sres_naptr_record_t const *nb = answers[j]->sr_naptr; |
1301 | |
1302 | if (na->na_order < nb->na_order) |
1303 | break; |
1304 | if (na->na_order > nb->na_order) |
1305 | continue; |
1306 | if (na->na_prefer < nb->na_prefer) |
1307 | break; |
1308 | } |
1309 | |
1310 | if (j < i) { |
1311 | sres_record_t *r = answers[i]; |
1312 | for (; j < i; i--) { |
1313 | answers[i] = answers[i - 1]; |
1314 | } |
1315 | answers[j] = r; |
1316 | } |
1317 | } |
1318 | } |
1319 | |
1320 | static void |
1321 | sres_sip_step_by_naptr(sres_sip_t *srs, |
1322 | struct srs_step *step0, |
1323 | uint16_t hint, |
1324 | sres_naptr_record_t const *na) |
1325 | { |
1326 | struct srs_step *step; |
1327 | uint16_t qtype; |
1328 | uint16_t port = srs->srs_hints[hint].hint_stp->stp_port; |
1329 | uint16_t hint_qtype = srs->srs_hints[hint].hint_qtype; |
1330 | |
1331 | if (na->na_flags[0] == 's' || na->na_flags[0] == 'S') |
1332 | /* "S" flag means that the next lookup should be for SRV records */ |
1333 | qtype = sres_type_srv; /* SRV */ |
1334 | else if (na->na_flags[0] == 'a' || na->na_flags[0] == 'A') |
1335 | /* "A" means that the next lookup should be A/AAAA */ |
1336 | qtype = hint_qtype; |
1337 | else |
1338 | return; |
1339 | |
1340 | step = sres_sip_step_new(srs, qtype, NULL((void*)0), na->na_replace); |
1341 | |
1342 | if (step == NULL((void*)0)) |
1343 | return; |
1344 | |
1345 | step->sp_trace = step0; |
1346 | step->sp_origin = (sres_record_t const *)na; |
1347 | step->sp_prefer = na->na_prefer; |
1348 | step->sp_priority = hint; |
1349 | step->sp_weight = 1; |
1350 | step->sp_hint = hint; |
1351 | step->sp_port = port; |
1352 | |
1353 | sres_sip_append_step(srs, step); |
1354 | } |
1355 | |
1356 | /* Process SRV records */ |
1357 | static void |
1358 | sres_sip_process_srv(sres_sip_t *srs, |
1359 | struct srs_step *step0, |
1360 | sres_record_t *answers[]) |
1361 | { |
1362 | int i; |
1363 | struct srs_hint *hint = &srs->srs_hints[step0->sp_hint]; |
1364 | |
1365 | sres_sip_sort_srv(answers); /* Sort by priority (only) */ |
1366 | |
1367 | for (i = 0; answers[i]; i++) { |
1368 | sres_srv_record_t const *srv = answers[i]->sr_srv; |
1369 | struct srs_step *step; |
1370 | |
1371 | if (srv->srv_record->r_status /* There was an error */ || |
1372 | srv->srv_record->r_type != sres_type_srv) |
1373 | continue; |
1374 | |
1375 | srs->srs_try_a = 0; |
1376 | |
1377 | step = sres_sip_step_new(srs, hint->hint_qtype, NULL((void*)0), srv->srv_target); |
1378 | if (step) { |
1379 | step->sp_hint = step0->sp_hint; |
1380 | step->sp_trace = step0; |
1381 | step->sp_origin = (sres_record_t const *)srv; |
1382 | step->sp_port = srv->srv_port; |
1383 | step->sp_prefer = step0->sp_prefer; |
1384 | step->sp_priority = srv->srv_priority; |
1385 | step->sp_weight = srv->srv_weight; |
1386 | |
1387 | /* Insert sorted by priority, randomly select by weigth */ |
1388 | sres_sip_insert_step(srs, step); |
1389 | } |
1390 | } |
1391 | } |
1392 | |
1393 | static void |
1394 | sres_sip_sort_srv(sres_record_t *answers[]) |
1395 | { |
1396 | int i, j; |
1397 | |
1398 | for (i = 0; answers[i]; i++) { |
1399 | sres_srv_record_t const *a = answers[i]->sr_srv; |
1400 | |
1401 | if (a->srv_record->r_type != sres_type_srv) |
1402 | break; |
1403 | |
1404 | for (j = 0; j < i; j++) { |
1405 | sres_srv_record_t const *b = answers[j]->sr_srv; |
1406 | |
1407 | if (a->srv_priority < b->srv_priority) |
1408 | break; |
1409 | } |
1410 | |
1411 | if (j < i) { |
1412 | sres_record_t *r = answers[i]; |
1413 | for (; j < i; i--) { |
1414 | answers[i] = answers[i - 1]; |
1415 | } |
1416 | answers[j] = r; |
1417 | } |
1418 | } |
1419 | } |
1420 | |
1421 | #if SU_HAVE_IN61 |
1422 | /* Process AAAA records */ |
1423 | static void |
1424 | sres_sip_process_aaaa(sres_sip_t *srs, |
1425 | struct srs_step *step, |
1426 | sres_record_t *answers[]) |
1427 | { |
1428 | struct srs_hint *hint = &srs->srs_hints[step->sp_hint]; |
1429 | struct sres_sip_tport const *stp = hint->hint_stp; |
1430 | su_addrinfo_t ai[1]; |
1431 | su_sockaddr_t su[1]; |
1432 | size_t i, j; |
1433 | |
1434 | for (i = j = 0; answers && answers[i]; i++) { |
1435 | sres_aaaa_record_t const *aaaa = answers[i]->sr_aaaa; |
1436 | |
1437 | if (aaaa->aaaa_record->r_status || |
1438 | aaaa->aaaa_record->r_type != sres_type_aaaa) |
1439 | continue; /* There was an error */ |
1440 | |
1441 | memset(ai, 0, (sizeof ai)); |
1442 | ai->ai_protocol = stp->stp_number; |
1443 | ai->ai_addr = memset(su, 0, ai->ai_addrlen = (sizeof su->su_sin6)); |
1444 | su->su_lensu_array[0] = (sizeof su->su_sin6); |
1445 | su->su_familysu_sa.sa_family = ai->ai_family = AF_INET610; |
1446 | su->su_portsu_sin.sin_port = htons(step->sp_port); |
1447 | |
1448 | memcpy(&su->su_sin6.sin6_addr, |
1449 | &aaaa->aaaa_addr, |
1450 | (sizeof aaaa->aaaa_addr)); |
1451 | |
1452 | ai->ai_canonname = aaaa->aaaa_record->r_name; |
1453 | |
1454 | sres_sip_append_result(srs, ai); |
1455 | } |
1456 | } |
1457 | #endif /* SU_HAVE_IN6 */ |
1458 | |
1459 | /* Process A records */ |
1460 | static void |
1461 | sres_sip_process_a(sres_sip_t *srs, |
1462 | struct srs_step *step, |
1463 | sres_record_t *answers[]) |
1464 | { |
1465 | struct srs_hint *hint = &srs->srs_hints[step->sp_hint]; |
1466 | struct sres_sip_tport const *stp = hint->hint_stp; |
1467 | su_addrinfo_t ai[1]; |
1468 | su_sockaddr_t su[1]; |
1469 | int i, j; |
1470 | |
1471 | for (i = j = 0; answers[i]; i++) { |
Although the value stored to 'j' is used in the enclosing expression, the value is never actually read from 'j' | |
1472 | sres_a_record_t const *a = answers[i]->sr_a; |
1473 | |
1474 | if (a->a_record->r_status || |
1475 | a->a_record->r_type != sres_type_a) |
1476 | continue; /* There was an error */ |
1477 | |
1478 | memset(ai, 0, (sizeof ai)); |
1479 | ai->ai_protocol = stp->stp_number; |
1480 | ai->ai_addr = memset(su, 0, ai->ai_addrlen = (sizeof su->su_sin)); |
1481 | su->su_lensu_array[0] = (sizeof su->su_sin); |
1482 | su->su_familysu_sa.sa_family = ai->ai_family = AF_INET2; |
1483 | su->su_portsu_sin.sin_port = htons(step->sp_port); |
1484 | |
1485 | memcpy(&su->su_sin.sin_addr, &a->a_addr, (sizeof a->a_addr)); |
1486 | |
1487 | ai->ai_canonname = a->a_record->r_name; |
1488 | |
1489 | sres_sip_append_result(srs, ai); |
1490 | } |
1491 | } |
1492 | |
1493 | static void |
1494 | sres_sip_process_cname(sres_sip_t *srs, |
1495 | struct srs_step *step0, |
1496 | sres_record_t *answers[]) |
1497 | { |
1498 | struct srs_step *step; |
1499 | int i; |
1500 | |
1501 | if (answers == NULL((void*)0)) |
1502 | return; |
1503 | |
1504 | for (i = 0; answers[i]; i++) { |
1505 | sres_cname_record_t *cn = answers[i]->sr_cname; |
1506 | |
1507 | if (cn->cn_record->r_type != sres_type_cname || |
1508 | cn->cn_record->r_status != SRES_OK) |
1509 | continue; |
1510 | |
1511 | step = sres_sip_step_new(srs, step0->sp_type, NULL((void*)0), cn->cn_cname); |
1512 | if (!step) |
1513 | return; |
1514 | |
1515 | step->sp_trace = step0; |
1516 | step->sp_origin = answers[i]; |
1517 | |
1518 | step->sp_hint = step0->sp_hint; |
1519 | step->sp_port = step0->sp_port; |
1520 | step->sp_prefer = step0->sp_prefer; |
1521 | step->sp_priority = step0->sp_priority; |
1522 | step->sp_weight = step0->sp_weight; |
1523 | |
1524 | sres_sip_insert_step(srs, step); |
1525 | |
1526 | return; |
1527 | } |
1528 | } |
1529 | |
1530 | |
1531 | /* Process URI with numeric host */ |
1532 | static void |
1533 | sres_sip_process_numeric(sres_sip_t *srs) |
1534 | { |
1535 | char const *target = srs->srs_target; |
1536 | su_addrinfo_t ai[1]; |
1537 | su_sockaddr_t su[1]; |
1538 | char buffer[64]; |
1539 | int i; |
1540 | |
1541 | memset(ai, 0, (sizeof ai)); (void)buffer; |
1542 | |
1543 | if (host_is_ip4_address(target)) { |
1544 | ai->ai_addr = memset(su, 0, ai->ai_addrlen = (sizeof su->su_sin)); |
1545 | su->su_lensu_array[0] = (sizeof su->su_sin); |
1546 | if (su_inet_ptoninet_pton(su->su_familysu_sa.sa_family = ai->ai_family = AF_INET2, |
1547 | target, &su->su_sin.sin_addr) <= 0) { |
1548 | srs->srs_error = SRES_SIP_ERR_BAD_URI; |
1549 | return; |
1550 | } |
1551 | } |
1552 | #if SU_HAVE_IN61 |
1553 | else if (host_is_ip6_address(target)) { |
1554 | ai->ai_addr = memset(su, 0, ai->ai_addrlen = (sizeof su->su_sin6)); |
1555 | su->su_lensu_array[0] = (sizeof su->su_sin6); |
1556 | if (su_inet_ptoninet_pton(su->su_familysu_sa.sa_family = ai->ai_family = AF_INET610, |
1557 | target, &su->su_sin6.sin6_addr) <= 0) { |
1558 | srs->srs_error = SRES_SIP_ERR_BAD_URI; |
1559 | return; |
1560 | } |
1561 | } |
1562 | else if (host_is_ip6_reference(target)) { |
1563 | size_t len = strlen(target) - 2; |
1564 | |
1565 | ai->ai_addr = memset(su, 0, ai->ai_addrlen = (sizeof su->su_sin6)); |
1566 | su->su_lensu_array[0] = (sizeof su->su_sin6); |
1567 | |
1568 | if (len >= sizeof buffer || |
1569 | !memcpy(buffer, target + 1, len) || |
1570 | (buffer[len] = 0) || |
1571 | su_inet_ptoninet_pton(su->su_familysu_sa.sa_family = ai->ai_family = AF_INET610, |
1572 | buffer, &su->su_sin6.sin6_addr) <= 0) { |
1573 | srs->srs_error = SRES_SIP_ERR_BAD_URI; |
1574 | return; |
1575 | } |
1576 | |
1577 | target = buffer; |
1578 | } |
1579 | #endif |
1580 | else { |
1581 | srs->srs_error = SRES_SIP_ERR_BAD_URI; |
1582 | return; |
1583 | } |
1584 | |
1585 | ai->ai_canonname = (char *)target; |
1586 | |
1587 | for (i = 1; srs->srs_hints[i].hint_stp; i++) { |
1588 | struct srs_hint const *hint = srs->srs_hints + i; |
1589 | |
1590 | /* Consider only transport from uri parameter */ |
1591 | if (!srs->srs_transport && |
1592 | /* ...or default transports for this URI type */ |
1593 | hint->hint_stp->stp_type != srs->srs_url->url_type) |
1594 | continue; |
1595 | |
1596 | #if SU_HAVE_IN61 |
1597 | if (ai->ai_family == AF_INET610 && |
1598 | srs->srs_hints[i].hint_qtype != sres_type_aaaa) |
1599 | continue; |
1600 | #endif |
1601 | ai->ai_protocol = srs->srs_hints[i].hint_stp->stp_number; |
1602 | sres_sip_append_result(srs, ai); |
1603 | } |
1604 | } |
1605 | |
1606 | /** Store A/AAAA query result */ |
1607 | static void |
1608 | sres_sip_append_result(sres_sip_t *srs, |
1609 | su_addrinfo_t const *result) |
1610 | { |
1611 | su_addrinfo_t *ai, **tail; |
1612 | int duplicate = 0; |
1613 | char const *canonname = result->ai_canonname; |
1614 | char numeric[64]; |
1615 | size_t clen = 0; |
1616 | |
1617 | for (ai = srs->srs_results; ai && !duplicate; ai = ai->ai_next) { |
1618 | duplicate = |
1619 | ai->ai_family == result->ai_family && |
1620 | ai->ai_protocol == result->ai_protocol && |
1621 | ai->ai_addrlen == result->ai_addrlen && |
1622 | !memcmp(ai->ai_addr, result->ai_addr, result->ai_addrlen); |
1623 | /* Note - different canonnames are not considered */ |
1624 | if (duplicate) |
1625 | break; |
1626 | } |
1627 | |
1628 | { |
1629 | unsigned port = 0; |
1630 | char const *lb = "", *rb = ""; |
1631 | |
1632 | if (result->ai_family == AF_INET2) { |
1633 | struct sockaddr_in const *sin = (struct sockaddr_in *)result->ai_addr; |
1634 | su_inet_ntopinet_ntop(AF_INET2, &sin->sin_addr, numeric, sizeof numeric); |
1635 | port = ntohs(sin->sin_port); |
1636 | } |
1637 | #if SU_HAVE_IN61 |
1638 | else if (result->ai_family == AF_INET610) { |
1639 | struct sockaddr_in6 const *sin6 = (struct sockaddr_in6 *)result->ai_addr; |
1640 | su_inet_ntopinet_ntop(AF_INET610, &sin6->sin6_addr, numeric, (sizeof numeric)); |
1641 | port = ntohs(sin6->sin6_port); |
1642 | lb = "[", rb = "]"; |
1643 | } |
1644 | #endif |
1645 | else { |
1646 | strcpy(numeric, "UNKNOWN"); |
1647 | } |
1648 | |
1649 | SU_DEBUG_5(("srs(%p): %s result %s%s%s:%u;transport=%s\n",(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 1652, "srs(%p): %s result %s%s%s:%u;transport=%s\n" , (void *)srs, duplicate ? "duplicate" : "returning", lb , numeric , rb, port, sres_sip_transport_name(result->ai_protocol))) : (void)0) |
1650 | (void *)srs, duplicate ? "duplicate" : "returning",(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 1652, "srs(%p): %s result %s%s%s:%u;transport=%s\n" , (void *)srs, duplicate ? "duplicate" : "returning", lb , numeric , rb, port, sres_sip_transport_name(result->ai_protocol))) : (void)0) |
1651 | lb , numeric, rb, port,(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 1652, "srs(%p): %s result %s%s%s:%u;transport=%s\n" , (void *)srs, duplicate ? "duplicate" : "returning", lb , numeric , rb, port, sres_sip_transport_name(result->ai_protocol))) : (void)0) |
1652 | sres_sip_transport_name(result->ai_protocol)))(((sresolv_log != ((void*)0) && sresolv_log->log_init ) == 0 ? 9 : ((sresolv_log != ((void*)0) && sresolv_log ->log_init > 1) ? sresolv_log->log_level : su_log_default ->log_level)) >= 5 ? (_su_llog(sresolv_log, 5, "sres_sip.c" , (const char *)__func__, 1652, "srs(%p): %s result %s%s%s:%u;transport=%s\n" , (void *)srs, duplicate ? "duplicate" : "returning", lb , numeric , rb, port, sres_sip_transport_name(result->ai_protocol))) : (void)0); |
1653 | |
1654 | if (srs->srs_numeric) |
1655 | canonname = numeric; |
1656 | } |
1657 | |
1658 | if (duplicate) |
1659 | return; |
1660 | |
1661 | if (!srs->srs_canonname) |
1662 | canonname = NULL((void*)0); |
1663 | if (canonname) { |
1664 | clen = strlen(canonname); |
1665 | if (clen && canonname[clen - 1] == '.') |
1666 | /* Do not include final dot in canonname */; |
1667 | else |
1668 | clen++; |
1669 | } |
1670 | |
1671 | ai = su_zalloc(srs->srs_home, (sizeof *ai) + result->ai_addrlen + clen); |
1672 | |
1673 | if (ai == NULL((void*)0)) |
1674 | return; |
1675 | |
1676 | *ai = *result; |
1677 | ai->ai_next = NULL((void*)0); |
1678 | ai->ai_addr = memcpy(ai + 1, ai->ai_addr, ai->ai_addrlen); |
1679 | if (canonname) { |
1680 | ai->ai_canonname = (char *)(ai->ai_addr) + ai->ai_addrlen; |
1681 | memcpy(ai->ai_canonname, canonname, clen - 1); |
1682 | ai->ai_canonname[clen - 1] = '\0'; |
1683 | } |
1684 | else { |
1685 | ai->ai_canonname = NULL((void*)0); |
1686 | } |
1687 | |
1688 | for (tail = srs->srs_next; *tail; tail = &(*tail)->ai_next) |
1689 | ; |
1690 | |
1691 | *tail = ai; |
1692 | |
1693 | srs->srs_error = 0; |
1694 | } |