Bug Summary

File:libsofia-sip-ua/sresolv/sres_sip.c
Warning:line 789, column 12
Although the value stored to 'process' is used in the enclosing expression, the value is never actually read from 'process'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name sres_sip.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib/llvm-11/lib/clang/11.0.1 -D HAVE_CONFIG_H -I . -I ../.. -I ../../libsofia-sip-ua/su/sofia-sip -I ./../url -I ../url -I ./../bnf -I ../bnf -I ./../su -I ../su -I ../../s2check -D SU_DEBUG=0 -D PIC -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-11/lib/clang/11.0.1/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir /drone/src/libsofia-sip-ua/sresolv -ferror-limit 19 -fgnuc-version=4.2.1 -analyzer-output=html -faddrsig -o /drone/src/scan-build/2022-06-23-181620-12-1 -x c sres_sip.c
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
36struct sres_sip_tport;
37struct srs_step;
38struct srs_hint;
39struct 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 */
67struct 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
78static 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
85struct srs_step;
86struct srs_hint;
87
88struct 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 */
130struct 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
168enum {
169 STEP_NEW = -4,
170 STEP_QUEUED = -3,
171 STEP_CACHED = -2,
172 STEP_SENT = -1,
173 STEP_OK = 0
174};
175
176static void _sres_sip_destruct(void *_srs);
177static sres_sip_t *sres_sip_fatal(sres_sip_t *srs, int error);
178static void sres_sip_hint(sres_sip_t *srs, int qtype, int protocol);
179static int sres_sip_url_transport(url_t const *uri);
180static char const *sres_sip_transport_name(int number);
181void sres_sip_graylist(sres_sip_t *srs, struct srs_step *step);
182
183static int sres_sip_is_waiting(sres_sip_t const *srs);
184static void sres_sip_return_results(sres_sip_t *srs, int final);
185
186static void sres_sip_try_next_steps(sres_sip_t *srs);
187static void sres_sip_try_naptr_steps(sres_sip_t *srs);
188static void sres_sip_try_srv_steps(sres_sip_t *srs);
189static void sres_sip_try_a_aaaa_steps(sres_sip_t *srs);
190
191static struct srs_step *sres_sip_step_new(
192 sres_sip_t *srs,
193 int type,
194 char const *prefix,
195 char const *domain);
196
197static void sres_sip_append_step(sres_sip_t *srs,
198 struct srs_step *step);
199
200static void sres_sip_insert_step(sres_sip_t *srs,
201 struct srs_step *step);
202
203static int sres_sip_send_steps(sres_sip_t *srs);
204static void sres_sip_answer(struct srs_step *step,
205 sres_query_t *q,
206 sres_record_t *answers[]);
207static int sres_sip_status_of_answers(sres_record_t *answers[], uint16_t type);
208static int sres_sip_count_answers(sres_record_t *answers[], uint16_t type);
209static void sres_sip_log_answers(sres_sip_t *srs,
210 struct srs_step *step,
211 sres_record_t *answers[]);
212
213static int sres_sip_process(sres_sip_t *srs);
214
215static void sres_sip_process_naptr(sres_sip_t *srs,
216 struct srs_step *nq,
217 sres_record_t *answers[]);
218static void sres_sip_sort_naptr(sres_record_t *answers[]);
219
220static 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
225static void sres_sip_process_srv(sres_sip_t *srs,
226 struct srs_step *nq,
227 sres_record_t *answers[]);
228
229static void sres_sip_sort_srv(sres_record_t *answers[]);
230
231#if SU_HAVE_IN61
232static void sres_sip_process_aaaa(sres_sip_t *srs, struct srs_step *,
233 sres_record_t *answers[]);
234#endif
235static void sres_sip_process_a(sres_sip_t *srs, struct srs_step *,
236 sres_record_t *answers[]);
237
238static void sres_sip_process_cname(sres_sip_t *srs,
239 struct srs_step *step0,
240 sres_record_t *answers[]);
241
242static void sres_sip_process_numeric(sres_sip_t *srs);
243
244static void sres_sip_append_result(sres_sip_t *srs,
245 su_addrinfo_t const *result);
246
247/** Resolve a SIP uri.
248 *
249 */
250sres_sip_t *
251sres_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
388sres_sip_t *
389sres_sip_ref(sres_sip_t *srs)
390{
391 return (sres_sip_t *)su_home_ref(srs->srs_home);
392}
393
394void
395sres_sip_unref(sres_sip_t *srs)
396{
397 su_home_unref(srs->srs_home);
398}
399
400static 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
421int
422sres_sip_error(sres_sip_t *srs)
423{
424 return srs ? srs->srs_error : SRES_SIP_ERR_FAULT;
425}
426
427su_addrinfo_t const *
428sres_sip_results(sres_sip_t *srs)
429{
430 return srs ? srs->srs_results : NULL((void*)0);
431}
432
433su_addrinfo_t const *
434sres_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
447static sres_sip_t *
448sres_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
455static void
456sres_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 */
501static int
502sres_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
527static char const *
528sres_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 */
541void
542sres_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 */
557static void
558sres_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 */
610int
611sres_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
642static int
643sres_sip_is_waiting(sres_sip_t const *srs)
644{
645 return *srs->srs_process && (*srs->srs_process)->sp_query;
646}
647
648static void
649sres_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. */
665static void
666sres_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. */
676static void
677sres_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. */
702static void
703sres_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 */
736static int
737sres_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;
Although the value stored to 'process' is used in the enclosing expression, the value is never actually read from 'process'
790 }
791
792 return process = 0;
793}
794
795static void
796sres_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
837static int
838sres_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
854static int
855sres_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
868static void
869sres_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 */
940static void
941sres_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
987static int
988sres_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
1042static struct srs_step *
1043sres_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 */
1093static void
1094sres_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 */
1117static void
1118sres_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 */
1210static void
1211sres_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
1288static void
1289sres_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
1320static void
1321sres_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 */
1357static void
1358sres_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
1393static void
1394sres_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 */
1423static void
1424sres_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 */
1460static void
1461sres_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++) {
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
1493static void
1494sres_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 */
1532static void
1533sres_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 */
1607static void
1608sres_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}