1 /*
2 * This file is part of the Sofia-SIP package
3 *
4 * Copyright (C) 2005 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 outbound.c
26 * @brief Implementation of SIP NAT traversal and outbound
27 *
28 * @author Pekka Pessi <Pekka.Pessi@nokia.com>
29 * @author Kai Vehmanen <Kai.Vehmanen@nokia.com>
30 * @author Martti Mela <Martti Mela@nokia.com>
31 *
32 * @date Created: Wed May 10 12:11:54 EEST 2006 ppessi
33 */
34
35 #include "config.h"
36
37 #define NTA_OUTGOING_MAGIC_T struct outbound
38
39 #include "outbound.h"
40
41 #include <sofia-sip/hostdomain.h>
42 #include <sofia-sip/sip.h>
43 #include <sofia-sip/sip_protos.h>
44 #include <sofia-sip/sip_util.h>
45 #include <sofia-sip/sip_status.h>
46 #include <sofia-sip/su_tagarg.h>
47 #include <sofia-sip/tport.h>
48 #include <sofia-sip/nta_tport.h>
49
50 #include <sofia-sip/su_md5.h>
51 #include <sofia-sip/su_uniqueid.h>
52 #include <sofia-sip/token64.h>
53
54 #define SU_LOG (nua_log)
55 #include <sofia-sip/su_debug.h>
56
57 #include <stddef.h>
58 #include <stdlib.h>
59 #include <string.h>
60 #include <stdio.h>
61 #include <assert.h>
62
63 struct outbound {
64 su_home_t ob_home[1];
65 outbound_owner_vtable
66 const *ob_oo; /**< Callbacks */
67 outbound_owner_t *ob_owner; /**< Backpointer */
68
69 su_root_t *ob_root; /**< Root for timers and stuff */
70 nta_agent_t *ob_nta; /**< SIP transactions */
71
72 char ob_cookie[32]; /**< Our magic cookie */
73
74 struct outbound_prefs {
75 unsigned interval; /**< Default keepalive interval for datagram */
76 unsigned stream_interval; /**< Default keepalive interval for streams */
77 unsigned gruuize:1; /**< Establish a GRUU */
78 unsigned outbound:1; /**< Try to use outbound */
79 unsigned natify:1; /**< Try to detect NAT */
80 signed okeepalive:2; /**< Connection keepalive with OPTIONS */
81 unsigned validate:1; /**< Validate registration with OPTIONS */
82 /* How to detect NAT binding or connect to outbound: */
83 unsigned use_connect:1; /**< Use HTTP connect */
84 unsigned use_rport:1; /**< Use received/rport */
85 unsigned use_socks:1; /**< Detect and use SOCKS V5 */
86 unsigned use_upnp:1; /**< Detect and use UPnP */
87 unsigned use_stun:1; /**< Detect and try to use STUN */
88 unsigned :0;
89 } ob_prefs;
90
91 struct outbound_info {
92 /* See enum outbound_feature: */
93 /* 0 do not support, 1 - perhaps supports, 2 - supports, 3 - requires */
94 unsigned gruu:2, outbound:2, pref:2;
95 } ob_info;
96
97 /** Source of Contact header */
98 unsigned ob_by_stack:1;
99 /** Self-generated contacts */
100 unsigned ob_contacts:1;
101
102 /* The registration state machine. */
103 /** Initial REGISTER containing ob_rcontact has been sent */
104 unsigned ob_registering:1;
105 /** 2XX response to REGISTER containing ob_rcontact has been received */
106 unsigned ob_registered:1;
107 /** The registration has been validated:
108 * We have successfully sent OPTIONS to ourselves.
109 */
110 unsigned ob_validated:1;
111 /** The registration has been validated once.
112 * We have successfully sent OPTIONS to ourselves, so do not give
113 * up if OPTIONS probe fails.
114 */
115 unsigned ob_once_validated:1;
116
117 unsigned ob_proxy_override:1; /**< Override stack default proxy */
118 unsigned :0;
119
120 url_string_t *ob_proxy; /**< Outbound-specific proxy */
121 char const *ob_instance; /**< Our instance ID */
122 int32_t ob_reg_id; /**< Flow-id */
123 sip_contact_t *ob_rcontact; /**< Our contact */
124 sip_contact_t *ob_dcontact; /**< Contact for dialogs */
125 sip_contact_t *ob_previous; /**< Stale contact */
126 sip_contact_t *ob_gruu; /**< Contact added to requests */
127 sip_via_t *ob_via; /**< Via header used to generate contacts */
128
129 sip_contact_t *ob_obp; /**< Contacts from outbound proxy */
130
131 char *ob_nat_detected; /**< Our public address */
132 char *ob_nat_port; /**< Our public port number */
133
134 void *ob_stun; /**< Stun context */
135 void *ob_upnp; /**< UPnP context */
136
137 struct {
138 char *sipstun; /**< Stun server usable for keep-alives */
139 unsigned interval; /**< Interval. */
140 su_timer_t *timer; /**< Keep-alive timer */
141 msg_t *msg; /**< Keep-alive OPTIONS message */
142 nta_outgoing_t *orq; /**< Keep-alive OPTIONS transaction */
143 auth_client_t *auc[1]; /**< Authenticator for OPTIONS */
144 /** Progress of registration validation */
145 unsigned validating:1, validated:1,:0;
146 } ob_keepalive; /**< Keepalive informatio */
147 };
148
149 static
150 int outbound_nat_detect(outbound_t *ob,
151 sip_t const *request,
152 sip_t const *response);
153
154 /** Return values for outbound_nat_detect(). */
155 enum {
156 ob_nat_error = -1, /* or anything below zero */
157 ob_no_nat = 0,
158 ob_nat_detected = 1,
159 ob_nat_changed = 2
160 };
161
162 /* ---------------------------------------------------------------------- */
163
164 #define SIP_METHOD_UNKNOWN sip_method_unknown, NULL
165
166 /** Content-Type sent in OPTIONS probing connectivity */
167 char const * const outbound_content_type = "application/vnd.nokia-register-usage";
168
169 static
170 int outbound_check_for_nat(outbound_t *ob,
171 sip_t const *request,
172 sip_t const *response);
173
174 enum outbound_feature {
175 outbound_feature_unsupported = 0,
176 outbound_feature_unsure = 1,
177 outbound_feature_supported = 2,
178 outbound_feature_required = 3
179 };
180
181 static enum outbound_feature feature_level(sip_t const *sip,
182 char const *tag, int level);
183
184 static int outbound_contacts_from_via(outbound_t *ob,
185 sip_via_t const *via);
186
187 /* ---------------------------------------------------------------------- */
188
189 /** Create a new outbound object */
190 outbound_t *
outbound_new(outbound_owner_t * owner,outbound_owner_vtable const * owner_methods,su_root_t * root,nta_agent_t * agent,char const * instance)191 outbound_new(outbound_owner_t *owner,
192 outbound_owner_vtable const *owner_methods,
193 su_root_t *root,
194 nta_agent_t *agent,
195 char const *instance)
196 {
197 outbound_t *ob;
198
199 if (!owner || !owner_methods || !root || !agent)
200 return NULL;
201
202 ob = su_home_clone((su_home_t *)owner, sizeof *ob);
203
204 if (ob) {
205 su_md5_t md5[1];
206 uint8_t digest[SU_MD5_DIGEST_SIZE];
207 su_guid_t guid[1];
208
209 ob->ob_owner = owner;
210 ob->ob_oo = owner_methods;
211 ob->ob_root = root;
212 ob->ob_nta = agent;
213
214 if (instance)
215 ob->ob_instance =
216 su_sprintf(ob->ob_home, "+sip.instance=\"<%s>\"", instance);
217 ob->ob_reg_id = 0;
218
219 outbound_peer_info(ob, NULL);
220
221 /* Generate a random cookie (used as Call-ID) for us */
222 su_md5_init(md5);
223 su_guid_generate(guid);
224 if (instance)
225 su_md5_update(md5, (void *)instance, strlen(instance));
226 su_md5_update(md5, (void *)guid, sizeof guid);
227 su_md5_digest(md5, digest);
228 token64_e(ob->ob_cookie, sizeof ob->ob_cookie, digest, sizeof digest);
229
230 if (instance && !ob->ob_instance)
231 su_home_unref(ob->ob_home), ob = NULL;
232 }
233
234 return ob;
235 }
236
outbound_unref(outbound_t * ob)237 void outbound_unref(outbound_t *ob)
238 {
239 if (ob->ob_keepalive.timer)
240 su_timer_destroy(ob->ob_keepalive.timer), ob->ob_keepalive.timer = NULL;
241
242 if (ob->ob_keepalive.orq)
243 nta_outgoing_destroy(ob->ob_keepalive.orq), ob->ob_keepalive.orq = NULL;
244
245 if (ob->ob_keepalive.msg)
246 msg_destroy(ob->ob_keepalive.msg), ob->ob_keepalive.msg = NULL;
247
248 su_home_unref(ob->ob_home);
249 }
250
251 #include <sofia-sip/bnf.h>
252
253 /** Set various outbound and nat-traversal related options. */
outbound_set_options(outbound_t * ob,char const * _options,unsigned interval,unsigned stream_interval)254 int outbound_set_options(outbound_t *ob,
255 char const *_options,
256 unsigned interval,
257 unsigned stream_interval)
258 {
259 struct outbound_prefs prefs[1] = {{ 0 }};
260 char *s, *options = su_strdup(NULL, _options);
261 int invalid;
262
263 prefs->interval = interval;
264 prefs->stream_interval = stream_interval;
265
266 #define MATCH(v) (len == sizeof(#v) - 1 && su_casenmatch(#v, s, len))
267
268 if (options) {
269 for (s = options; s[0]; s++) if (s[0] == '-') s[0] = '_';
270 }
271
272 prefs->gruuize = 1;
273 prefs->outbound = 0;
274 prefs->natify = 1;
275 prefs->okeepalive = -1;
276 prefs->validate = 1;
277 prefs->use_rport = 1;
278
279 for (s = options; s && s[0]; ) {
280 size_t len = span_token(s);
281 int value = 1;
282
283 if (len > 3 && su_casenmatch(s, "no_", 3))
284 value = 0, s += 3, len -= 3;
285 else if (len > 4 && su_casenmatch(s, "not_", 4))
286 value = 0, s += 4, len -= 4;
287
288 if (len == 0)
289 break;
290 else if (MATCH(gruuize)) prefs->gruuize = value;
291 else if (MATCH(outbound)) prefs->outbound = value;
292 else if (MATCH(natify)) prefs->natify = value;
293 else if (MATCH(validate)) prefs->validate = value;
294 else if (MATCH(options_keepalive)) prefs->okeepalive = value;
295 else if (MATCH(use_connect)) prefs->use_connect = value;
296 else if (MATCH(use_rport)) prefs->use_rport = value;
297 else if (MATCH(use_socks)) prefs->use_socks = value;
298 else if (MATCH(use_upnp)) prefs->use_upnp = value;
299 else if (MATCH(use_stun)) prefs->use_stun = value;
300 else
301 SU_DEBUG_1(("outbound(%p): unknown option \"%.*s\"\n",
302 (void *)ob->ob_owner, (int)len, s));
303
304 s += len;
305 len = strspn(s, " \t\n\r,;");
306 if (len == 0)
307 break;
308 s += len;
309 }
310
311 invalid = s && s[0];
312 if (invalid)
313 SU_DEBUG_1(("outbound(%p): invalid options \"%s\"\n",
314 (void *)ob->ob_owner, options));
315 su_free(NULL, options);
316 if (invalid)
317 return -1;
318
319 if (prefs->natify &&
320 !(prefs->outbound ||
321 prefs->use_connect ||
322 prefs->use_rport ||
323 prefs->use_socks ||
324 prefs->use_upnp ||
325 prefs->use_stun)) {
326 SU_DEBUG_1(("outbound(%p): no nat traversal method given\n",
327 (void *)ob->ob_owner));
328 }
329
330 ob->ob_prefs = *prefs;
331 ob->ob_reg_id = prefs->outbound ? 1 : 0;
332
333 return 0;
334 }
335
336 /** Override stack default proxy for outbound */
outbound_set_proxy(outbound_t * ob,url_string_t * proxy)337 int outbound_set_proxy(outbound_t *ob,
338 url_string_t *proxy)
339 {
340 url_string_t *new_proxy = NULL, *old_proxy = ob->ob_proxy;
341
342 if (proxy)
343 new_proxy = (url_string_t *)url_as_string(ob->ob_home, proxy->us_url);
344
345 if (proxy == NULL || new_proxy != NULL) {
346 ob->ob_proxy_override = 1;
347 ob->ob_proxy = new_proxy;
348 su_free(ob->ob_home, old_proxy);
349 return 0;
350 }
351
352 return -1;
353 }
354
355 /* ---------------------------------------------------------------------- */
356
357 /** Obtain contacts for REGISTER */
outbound_get_contacts(outbound_t * ob,sip_contact_t ** return_current_contact,sip_contact_t ** return_previous_contact)358 int outbound_get_contacts(outbound_t *ob,
359 sip_contact_t **return_current_contact,
360 sip_contact_t **return_previous_contact)
361 {
362 if (ob) {
363 if (ob->ob_contacts)
364 *return_current_contact = ob->ob_rcontact;
365 *return_previous_contact = ob->ob_previous;
366 }
367 return 0;
368 }
369
370 /** REGISTER request has been sent */
outbound_start_registering(outbound_t * ob)371 int outbound_start_registering(outbound_t *ob)
372 {
373 if (ob)
374 ob->ob_registering = 1;
375 return 0;
376 }
377
378 /** Process response to REGISTER request */
outbound_register_response(outbound_t * ob,int terminating,sip_t const * request,sip_t const * response)379 int outbound_register_response(outbound_t *ob,
380 int terminating,
381 sip_t const *request,
382 sip_t const *response)
383 {
384 int status, reregister;
385
386 if (!ob)
387 return 0;
388
389 if (terminating) {
390 ob->ob_registering = ob->ob_registered = 0;
391 return 0; /* Cleanup is done separately */
392 }
393
394 if (!response || !request)
395 return 0;
396
397 assert(request->sip_request); assert(response->sip_status);
398
399 status = response->sip_status->st_status;
400
401 if (status < 300) {
402 if (request->sip_contact && response->sip_contact) {
403 if (ob->ob_rcontact != NULL)
404 msg_header_free(ob->ob_home, (msg_header_t *)ob->ob_rcontact);
405 ob->ob_rcontact = sip_contact_dup(ob->ob_home, request->sip_contact);
406 ob->ob_registered = ob->ob_registering;
407 } else
408 ob->ob_registered = 0;
409 }
410
411 reregister = outbound_check_for_nat(ob, request, response);
412 if (reregister)
413 return reregister;
414
415 if (ob->ob_previous && status < 300) {
416 msg_header_free(ob->ob_home, (void *)ob->ob_previous);
417 ob->ob_previous = NULL;
418 }
419
420 return 0;
421 }
422
423
424 /** @internal Check if there is a NAT between us and registrar.
425 *
426 * @retval -1 upon an error
427 * @retval #ob_register_ok (0) if the registration was OK
428 * @retval #ob_reregister (1) if client needs to re-register
429 * @retval #ob_reregister_now (2) if client needs to re-register immediately
430 */
431 static
outbound_check_for_nat(outbound_t * ob,sip_t const * request,sip_t const * response)432 int outbound_check_for_nat(outbound_t *ob,
433 sip_t const *request,
434 sip_t const *response)
435 {
436 int binding_changed;
437 sip_contact_t *m = ob->ob_rcontact;
438
439 /* Update NAT information */
440 binding_changed = outbound_nat_detect(ob, request, response);
441
442 if (!ob->ob_nat_detected)
443 return ob_no_nat;
444
445 /* Contact was set by application, do not change it */
446 if (!ob->ob_by_stack)
447 return ob_no_nat;
448
449 /* Application does not want us to do any NAT traversal */
450 if (!ob->ob_prefs.natify)
451 return ob_no_nat;
452
453 /* We have detected NAT. Now, what to do?
454 * 1) do nothing - register as usual and let proxy take care of it?
455 * 2) try to detect our public nat binding and use it
456 * 2A) use public vias from nta generated by STUN or UPnP
457 * 2B) use SIP Via header
458 */
459
460 /* Do we have to ask for reregistration */
461 if (!m || binding_changed >= ob_nat_changed) {
462 if (ob->ob_stun) {
463 /* Use STUN? */
464 return ob_reregister;
465 }
466 else if (ob->ob_upnp) {
467 /* Use UPnP */
468 return ob_reregister;
469 }
470 else {
471 if (outbound_contacts_from_via(ob, response->sip_via) < 0)
472 return -1;
473 }
474
475 return ob_reregister_now;
476 }
477
478 return 0;
479 }
480
481 /**@internal
482 *
483 * Detect NAT.
484 *
485 * Based on "received" and possible "rport" parameters in the top-most Via,
486 * check and update our NAT status.
487 *
488 * @retval ob_nat_changed (2) change in public NAT binding detected
489 * @retval ob_nat_detected (1) NAT binding detected
490 * @retval ob_no_nat (0) no NAT binding detected
491 * @retval -1 an error occurred
492 */
493 static
outbound_nat_detect(outbound_t * ob,sip_t const * request,sip_t const * response)494 int outbound_nat_detect(outbound_t *ob,
495 sip_t const *request,
496 sip_t const *response)
497 {
498 sip_via_t const *v;
499 int one = 1;
500 char const *received, *rport;
501 char *nat_detected, *nat_port;
502 char *new_detected, *new_port;
503
504 assert(request && request->sip_request);
505 assert(response && response->sip_status);
506
507 if (!ob || !response || !response->sip_via || !request->sip_via)
508 return -1;
509
510 v = response->sip_via;
511
512 received = v->v_received;
513 if (!received || !strcmp(received, request->sip_via->v_host))
514 return 0;
515
516 if (!host_is_ip_address(received)) {
517 if (received[0])
518 SU_DEBUG_3(("outbound(%p): Via with invalid received=%s\n",
519 (void *)ob->ob_owner, received));
520 return 0;
521 }
522
523 rport = sip_via_port(v, &one); assert(rport);
524
525 nat_detected = ob->ob_nat_detected;
526 nat_port = ob->ob_nat_port;
527
528 if (nat_detected && host_cmp(received, nat_detected) == 0) {
529 if (nat_port && su_casematch(rport, nat_port))
530 return 1;
531 if (!v->v_rport || !v->v_rport[0])
532 return 1;
533 }
534
535 if (!nat_detected) {
536 SU_DEBUG_5(("outbound(%p): detected NAT: %s != %s\n",
537 (void *)ob->ob_owner, v->v_host, received));
538 if (ob->ob_oo && ob->ob_oo->oo_status)
539 ob->ob_oo->oo_status(ob->ob_owner, ob, 101, "NAT detected", TAG_END());
540 }
541 else {
542 SU_DEBUG_5(("outbound(%p): NAT binding changed: "
543 "[%s]:%s != [%s]:%s\n",
544 (void *)ob->ob_owner, nat_detected, nat_port, received, rport));
545 if (ob->ob_oo && ob->ob_oo->oo_status)
546 ob->ob_oo->oo_status(ob->ob_owner, ob, 102, "NAT binding changed", TAG_END());
547 }
548
549 /* Save our nat binding */
550 new_detected = su_strdup(ob->ob_home, received);
551 new_port = su_strdup(ob->ob_home, rport);
552
553 if (!new_detected || !new_port) {
554 su_free(ob->ob_home, new_detected);
555 su_free(ob->ob_home, new_port);
556 return -1;
557 }
558
559 ob->ob_nat_detected = new_detected;
560 ob->ob_nat_port = new_port;
561
562 su_free(ob->ob_home, nat_detected);
563 su_free(ob->ob_home, nat_port);
564
565 return 2;
566 }
567
568 /* ---------------------------------------------------------------------- */
569
570 /** Convert "gruu" parameter returned by registrar to Contact header. */
outbound_gruuize(outbound_t * ob,sip_t const * sip)571 int outbound_gruuize(outbound_t *ob, sip_t const *sip)
572 {
573 sip_contact_t *m = NULL;
574 char *gruu;
575
576 if (!ob)
577 return 0;
578
579 if (ob->ob_rcontact == NULL)
580 return -1;
581
582 if (!ob->ob_prefs.gruuize && ob->ob_instance) {
583 char const *my_instance, *my_reg_id = NULL;
584 char const *instance, *reg_id;
585
586 m = ob->ob_rcontact;
587 my_instance = msg_header_find_param(m->m_common, "+sip.instance=");
588 if (my_instance)
589 my_reg_id = msg_header_find_param(m->m_common, "reg-id=");
590
591 for (m = sip->sip_contact; m; m = m->m_next) {
592 if (my_instance) {
593 instance = msg_header_find_param(m->m_common, "+sip.instance=");
594 if (!instance || strcmp(instance, my_instance))
595 continue;
596 if (my_reg_id) {
597 reg_id = msg_header_find_param(m->m_common, "reg-id=");
598 if (!reg_id || strcmp(reg_id, my_reg_id))
599 continue;
600 }
601 }
602
603 if (url_cmp_all(ob->ob_rcontact->m_url, m->m_url) == 0)
604 break;
605 }
606 }
607
608 if (m == NULL) {
609 if (ob->ob_gruu)
610 msg_header_free(ob->ob_home, (void *)ob->ob_gruu), ob->ob_gruu = NULL;
611 return 0;
612 }
613
614 gruu = (char *)msg_header_find_param(m->m_common, "pub-gruu=");
615
616 if (gruu == NULL || gruu[0] == '\0')
617 gruu = (char *)msg_header_find_param(m->m_common, "gruu=");
618
619 if (gruu == NULL || gruu[0] == '\0')
620 return 0;
621
622 gruu = msg_unquote_dup(NULL, gruu);
623 m = gruu ? sip_contact_format(ob->ob_home, "<%s>", gruu) : NULL;
624 su_free(NULL, gruu);
625
626 if (!m)
627 return -1;
628
629 if (ob->ob_gruu)
630 msg_header_free(ob->ob_home, (void *)ob->ob_gruu);
631 ob->ob_gruu = m;
632
633 return 0;
634 }
635
636 /* ---------------------------------------------------------------------- */
637
638 static int create_keepalive_message(outbound_t *ob,
639 sip_t const *register_request);
640
641 static int keepalive_options(outbound_t *ob);
642 static int keepalive_options_with_registration_probe(outbound_t *ob);
643
644 static int response_to_keepalive_options(outbound_t *ob,
645 nta_outgoing_t *orq,
646 sip_t const *sip);
647 static int process_response_to_keepalive_options(outbound_t *ob,
648 nta_outgoing_t *orq,
649 sip_t const *sip,
650 int status,
651 char const *phrase);
652
653 static void keepalive_timer(su_root_magic_t *root_magic,
654 su_timer_t *t,
655 su_timer_arg_t *ob_as_timer_arg);
656
657 /** Start OPTIONS keepalive or contact validation process */
outbound_start_keepalive(outbound_t * ob,nta_outgoing_t * register_transaction)658 void outbound_start_keepalive(outbound_t *ob,
659 nta_outgoing_t *register_transaction)
660 {
661 unsigned interval = 0;
662 int need_to_validate, udp;
663
664 if (!ob)
665 return;
666
667 udp = ob->ob_via && ob->ob_via->v_protocol == sip_transport_udp;
668
669 if (/* ob->ob_prefs.natify && */
670 /* On UDP, use OPTIONS keepalive by default */
671 (udp ? ob->ob_prefs.okeepalive != 0
672 /* Otherwise, only if requested */
673 : ob->ob_prefs.okeepalive > 0))
674 interval = ob->ob_prefs.interval;
675 need_to_validate = ob->ob_prefs.validate && !ob->ob_validated;
676
677 if (!register_transaction ||
678 !(need_to_validate || interval != 0)) {
679 outbound_stop_keepalive(ob);
680 return;
681 }
682
683 if (ob->ob_keepalive.timer)
684 su_timer_destroy(ob->ob_keepalive.timer), ob->ob_keepalive.timer = NULL;
685
686 if (interval) {
687 su_duration_t max_defer;
688
689 max_defer = su_root_get_max_defer(ob->ob_root);
690 if ((su_duration_t)interval >= max_defer) {
691 interval -= max_defer - 100;
692 }
693
694 ob->ob_keepalive.timer =
695 su_timer_create(su_root_task(ob->ob_root), interval);
696
697 su_timer_deferrable(ob->ob_keepalive.timer, 1);
698 }
699
700 ob->ob_keepalive.interval = interval;
701
702 if (!ob->ob_validated && ob->ob_keepalive.sipstun
703 && 0 /* Stun is disabled for now */) {
704 nta_tport_keepalive(register_transaction);
705 }
706 else {
707 if (register_transaction) {
708 msg_t *msg = nta_outgoing_getrequest(register_transaction);
709 sip_t const *register_request = sip_object(msg);
710 create_keepalive_message(ob, register_request);
711 msg_destroy(msg);
712 }
713
714 keepalive_options(ob);
715 }
716 }
717
outbound_stop_keepalive(outbound_t * ob)718 void outbound_stop_keepalive(outbound_t *ob)
719 {
720 if (!ob)
721 return;
722
723 ob->ob_keepalive.interval = 0;
724
725 if (ob->ob_keepalive.timer)
726 su_timer_destroy(ob->ob_keepalive.timer), ob->ob_keepalive.timer = NULL;
727
728 if (ob->ob_keepalive.orq)
729 nta_outgoing_destroy(ob->ob_keepalive.orq), ob->ob_keepalive.orq = NULL;
730
731 if (ob->ob_keepalive.msg)
732 msg_destroy(ob->ob_keepalive.msg), ob->ob_keepalive.msg = NULL;
733 }
734
735 /** @internal Create a message template for keepalive. */
create_keepalive_message(outbound_t * ob,sip_t const * regsip)736 static int create_keepalive_message(outbound_t *ob, sip_t const *regsip)
737 {
738 msg_t *msg = nta_msg_create(ob->ob_nta, MSG_FLG_COMPACT), *previous;
739 sip_t *osip = sip_object(msg);
740 sip_contact_t *m = ob->ob_rcontact;
741
742 unsigned d = ob->ob_keepalive.interval;
743
744 if (msg == NULL)
745 return -1;
746
747 assert(regsip); assert(regsip->sip_request);
748
749 if (m && m->m_params) {
750 sip_accept_contact_t *ac;
751 size_t i;
752 int features = 0;
753
754 ac = sip_accept_contact_make(msg_home(msg), "*;require;explicit");
755
756 for (i = 0; m->m_params[i]; i++) {
757 char const *s = m->m_params[i];
758 if (!sip_is_callerpref(s))
759 continue;
760 features++;
761 s = su_strdup(msg_home(msg), s);
762 msg_header_add_param(msg_home(msg), ac->cp_common, s);
763 }
764
765 if (features)
766 msg_header_insert(msg, NULL, (void *)ac);
767 else
768 msg_header_free(msg_home(msg), (void *)ac);
769 }
770
771 if (0 >
772 /* Duplicate essential headers from REGISTER request: */
773 sip_add_tl(msg, osip,
774 SIPTAG_TO(regsip->sip_to),
775 SIPTAG_FROM(regsip->sip_from),
776 /* XXX - we should only use loose routing here */
777 /* XXX - if we used strict routing,
778 the route header/request_uri must be restored
779 */
780 SIPTAG_ROUTE(regsip->sip_route),
781 /* Add Max-Forwards 0 */
782 TAG_IF(d, SIPTAG_MAX_FORWARDS_STR("0")),
783 TAG_IF(d, SIPTAG_SUBJECT_STR("KEEPALIVE")),
784 SIPTAG_CALL_ID_STR(ob->ob_cookie),
785 SIPTAG_ACCEPT_STR(outbound_content_type),
786 TAG_END()) ||
787 /* Create request-line, Call-ID, CSeq */
788 nta_msg_request_complete(msg,
789 nta_default_leg(ob->ob_nta),
790 SIP_METHOD_OPTIONS,
791 (void *)regsip->sip_to->a_url) < 0 ||
792 msg_serialize(msg, (void *)osip) < 0 ||
793 msg_prepare(msg) < 0)
794 return msg_destroy(msg), -1;
795
796 previous = ob->ob_keepalive.msg;
797 ob->ob_keepalive.msg = msg;
798 msg_destroy(previous);
799
800 return 0;
801 }
802
keepalive_options(outbound_t * ob)803 static int keepalive_options(outbound_t *ob)
804 {
805 msg_t *req;
806 sip_t *sip;
807
808 if (ob->ob_keepalive.orq)
809 return 0;
810
811 if (ob->ob_prefs.validate && ob->ob_registered && !ob->ob_validated)
812 return keepalive_options_with_registration_probe(ob);
813
814 req = msg_copy(ob->ob_keepalive.msg);
815 if (!req)
816 return -1;
817 sip = sip_object(req); assert(sip); assert(sip->sip_request);
818
819 if (nta_msg_request_complete(req, nta_default_leg(ob->ob_nta),
820 SIP_METHOD_UNKNOWN, NULL) < 0)
821 return msg_destroy(req), -1;
822
823 if (ob->ob_keepalive.auc[0])
824 auc_authorization(ob->ob_keepalive.auc, req, (void *)sip,
825 "OPTIONS", sip->sip_request->rq_url, sip->sip_payload);
826
827 ob->ob_keepalive.orq =
828 nta_outgoing_mcreate(ob->ob_nta,
829 response_to_keepalive_options,
830 ob,
831 NULL,
832 req,
833 TAG_IF(ob->ob_proxy_override,
834 NTATAG_DEFAULT_PROXY(ob->ob_proxy)),
835 TAG_END());
836
837 if (!ob->ob_keepalive.orq)
838 return msg_destroy(req), -1;
839
840 return 0;
841 }
842
response_to_keepalive_options(outbound_t * ob,nta_outgoing_t * orq,sip_t const * sip)843 static int response_to_keepalive_options(outbound_t *ob,
844 nta_outgoing_t *orq,
845 sip_t const *sip)
846 {
847 int status = 408;
848 char const *phrase = sip_408_Request_timeout;
849
850 if (sip && sip->sip_status) {
851 status = sip->sip_status->st_status;
852 phrase = sip->sip_status->st_phrase;
853 }
854
855 if (status == 100) {
856 /* This probably means that we are in trouble. whattodo, whattodo */
857 }
858
859 if (status >= 200) {
860 if (orq == ob->ob_keepalive.orq)
861 ob->ob_keepalive.orq = NULL;
862 process_response_to_keepalive_options(ob, orq, sip, status, phrase);
863 nta_outgoing_destroy(orq);
864 }
865
866 return 0;
867 }
868
process_response_to_keepalive_options(outbound_t * ob,nta_outgoing_t * orq,sip_t const * sip,int status,char const * phrase)869 static int process_response_to_keepalive_options(outbound_t *ob,
870 nta_outgoing_t *orq,
871 sip_t const *sip,
872 int status,
873 char const *phrase)
874 {
875 int binding_check;
876 int challenged = 0, credentials = 0;
877 msg_t *_reqmsg = nta_outgoing_getrequest(orq);
878 sip_t *request = sip_object(_reqmsg); msg_destroy(_reqmsg);
879
880 if (sip == NULL) {
881 SU_DEBUG_3(("outbound(%p): keepalive %u %s\n", (void *)ob->ob_owner,
882 status, phrase));
883 ob->ob_oo->oo_keepalive_error(ob->ob_owner, ob, status, phrase, TAG_END());
884 return 0;
885 }
886
887 if (status == 401 || status == 407) {
888 if (sip->sip_www_authenticate)
889 challenged += auc_challenge(ob->ob_keepalive.auc,
890 ob->ob_home,
891 sip->sip_www_authenticate,
892 sip_authorization_class) > 0;
893 if (sip->sip_proxy_authenticate)
894 challenged += auc_challenge(ob->ob_keepalive.auc,
895 ob->ob_home,
896 sip->sip_proxy_authenticate,
897 sip_proxy_authorization_class) > 0;
898 if (ob->ob_oo->oo_credentials)
899 credentials = ob->ob_oo->oo_credentials(ob->ob_owner,
900 ob->ob_keepalive.auc);
901 }
902
903 binding_check = outbound_nat_detect(ob, request, sip);
904
905 if (binding_check > 1) {
906 /* Bindings have changed */
907 if (outbound_contacts_from_via(ob, sip->sip_via) == 0) {
908 /* XXX - Destroy old keepalive template message */
909
910 /* re-REGISTER */
911 ob->ob_oo->oo_refresh(ob->ob_owner, ob);
912 return 0;
913 }
914 }
915
916 if (binding_check <= 1 && ob->ob_registered && ob->ob_keepalive.validating) {
917 int failed = 0;
918 unsigned loglevel = 3;
919
920 if (challenged > 0 && credentials > 0) {
921 keepalive_options_with_registration_probe(ob);
922 return 0;
923 }
924
925 if (status < 300 && ob->ob_keepalive.validated) {
926 loglevel = 5;
927 if (ob->ob_validated)
928 loglevel = 99; /* only once */
929 ob->ob_validated = ob->ob_once_validated = 1;
930 }
931 else if (status == 401 || status == 407 || status == 403)
932 loglevel = 5, failed = 1;
933 else
934 loglevel = 3, failed = 1;
935
936 if (loglevel >= SU_LOG->log_level) {
937 sip_contact_t const *m = ob->ob_rcontact;
938
939 if (m)
940 su_llog(SU_LOG, loglevel,
941 "outbound(%p): %s <" URL_PRINT_FORMAT ">\n",
942 (void *)ob->ob_owner,
943 failed ? "FAILED to validate" : "validated",
944 URL_PRINT_ARGS(m->m_url));
945 else
946 su_llog(SU_LOG, loglevel,
947 "outbound(%p): %s registration\n",
948 (void *)ob->ob_owner,
949 failed ? "FAILED to validate" : "validated");
950
951 if (failed)
952 su_llog(SU_LOG, loglevel, "outbound(%p): FAILED with %u %s\n",
953 (void *)ob->ob_owner, status, phrase);
954 }
955
956 if (failed)
957 ob->ob_oo->oo_probe_error(ob->ob_owner, ob, status, phrase, TAG_END());
958 }
959 else if (status == 408) {
960 SU_DEBUG_3(("outbound(%p): keepalive timeout\n", (void *)ob->ob_owner));
961 ob->ob_oo->oo_keepalive_error(ob->ob_owner, ob, status, phrase, TAG_END());
962 return 0;
963 }
964
965 ob->ob_keepalive.validating = 0;
966
967 if (ob->ob_keepalive.timer)
968 su_timer_set(ob->ob_keepalive.timer, keepalive_timer, ob);
969
970 return 0;
971 }
972
keepalive_timer(su_root_magic_t * root_magic,su_timer_t * t,su_timer_arg_t * ob_casted_as_timer_arg)973 static void keepalive_timer(su_root_magic_t *root_magic,
974 su_timer_t *t,
975 su_timer_arg_t *ob_casted_as_timer_arg)
976 {
977 outbound_t *ob = (outbound_t *)ob_casted_as_timer_arg;
978
979 (void)root_magic;
980
981 if (keepalive_options(ob) < 0)
982 su_timer_set(t, keepalive_timer, ob_casted_as_timer_arg); /* XXX */
983 }
984
985
986 /** @internal Send a keepalive OPTIONS that probes the registration */
keepalive_options_with_registration_probe(outbound_t * ob)987 static int keepalive_options_with_registration_probe(outbound_t *ob)
988 {
989 msg_t *req;
990 sip_t *sip;
991 void *request_uri;
992
993 if (ob->ob_keepalive.orq)
994 return 0;
995
996 req = msg_copy(ob->ob_keepalive.msg);
997 if (!req)
998 return -1;
999
1000 sip = sip_object(req); assert(sip);
1001 request_uri = sip->sip_to->a_url;
1002
1003 if (nta_msg_request_complete(req, nta_default_leg(ob->ob_nta),
1004 SIP_METHOD_OPTIONS, request_uri) < 0)
1005 return msg_destroy(req), -1;
1006
1007 if (ob->ob_keepalive.auc[0])
1008 auc_authorization(ob->ob_keepalive.auc, req, (void *)sip,
1009 "OPTIONS", request_uri, sip->sip_payload);
1010
1011 ob->ob_keepalive.orq =
1012 nta_outgoing_mcreate(ob->ob_nta,
1013 response_to_keepalive_options,
1014 ob,
1015 NULL,
1016 req,
1017 TAG_IF(ob->ob_proxy_override,
1018 NTATAG_DEFAULT_PROXY(ob->ob_proxy)),
1019 SIPTAG_SUBJECT_STR("REGISTRATION PROBE"),
1020 /* NONE is used to remove
1021 Max-Forwards: 0 found in ordinary keepalives */
1022 SIPTAG_MAX_FORWARDS(SIP_NONE),
1023 TAG_END());
1024
1025 if (!ob->ob_keepalive.orq)
1026 return msg_destroy(req), -1;
1027
1028 ob->ob_keepalive.validating = 1;
1029 ob->ob_keepalive.validated = 0;
1030
1031 return 0;
1032 }
1033
1034 /** Check if request should be processed by outbound */
outbound_targeted_request(sip_t const * sip)1035 int outbound_targeted_request(sip_t const *sip)
1036 {
1037 return
1038 sip && sip->sip_request &&
1039 sip->sip_request->rq_method == sip_method_options &&
1040 sip->sip_accept &&
1041 sip->sip_accept->ac_type &&
1042 su_casematch(sip->sip_accept->ac_type, outbound_content_type);
1043 }
1044
1045 /** Answer to the connectivity probe OPTIONS */
outbound_process_request(outbound_t * ob,nta_incoming_t * irq,sip_t const * sip)1046 int outbound_process_request(outbound_t *ob,
1047 nta_incoming_t *irq,
1048 sip_t const *sip)
1049 {
1050 /* XXX - We assume that Call-ID is not modified. */
1051 if (strcmp(sip->sip_call_id->i_id, ob->ob_cookie))
1052 return 0;
1053
1054 if (ob->ob_keepalive.validating) {
1055 SU_DEBUG_5(("outbound(%p): registration check OPTIONS received\n",
1056 (void *)ob->ob_owner));
1057 ob->ob_keepalive.validated = 1;
1058 }
1059
1060 nta_incoming_treply(irq, SIP_200_OK,
1061 SIPTAG_CONTENT_TYPE_STR(outbound_content_type),
1062 SIPTAG_PAYLOAD_STR(ob->ob_cookie),
1063 TAG_END());
1064 return 200;
1065 }
1066
1067
1068 /* ---------------------------------------------------------------------- */
1069
1070 /**@internal
1071 * Create contacts for outbound.
1072 *
1073 * There are two contacts:
1074 * one suitable for registrations (ob_rcontact) and another that can be used
1075 * in dialogs (ob_dcontact).
1076 */
outbound_contacts_from_via(outbound_t * ob,sip_via_t const * via)1077 int outbound_contacts_from_via(outbound_t *ob, sip_via_t const *via)
1078 {
1079 su_home_t *home = ob->ob_home;
1080 sip_contact_t *rcontact, *dcontact;
1081 char reg_id_param[20] = "";
1082 sip_contact_t *previous_previous, *previous_rcontact, *previous_dcontact;
1083 sip_via_t *v, v0[1], *previous_via;
1084 int contact_uri_changed;
1085
1086 if (!via)
1087 return -1;
1088
1089 v = v0; *v0 = *via; v0->v_next = NULL;
1090
1091 dcontact = ob->ob_oo->oo_contact(ob->ob_owner, home, 1,
1092 v, v->v_protocol, NULL);
1093
1094 if (ob->ob_instance && ob->ob_reg_id != 0)
1095 snprintf(reg_id_param, sizeof reg_id_param, ";reg-id=%u", ob->ob_reg_id);
1096
1097 rcontact = ob->ob_oo->oo_contact(ob->ob_owner, home, 0,
1098 v, v->v_protocol,
1099 ob->ob_instance, reg_id_param, NULL);
1100
1101 v = sip_via_dup(home, v);
1102
1103 if (!rcontact || !dcontact || !v) {
1104 msg_header_free(home, (void *)dcontact);
1105 if (rcontact != dcontact)
1106 msg_header_free(home, (void *)rcontact);
1107 msg_header_free(home, (void *)v);
1108 return -1;
1109 }
1110
1111 contact_uri_changed = !ob->ob_rcontact ||
1112 url_cmp_all(ob->ob_rcontact->m_url, rcontact->m_url);
1113
1114 if (contact_uri_changed) {
1115 previous_previous = ob->ob_previous;
1116 previous_dcontact = ob->ob_dcontact;
1117 previous_via = ob->ob_via;
1118
1119 if (ob->ob_registered
1120 /* && (ob->ob_reg_id == 0 || ob->ob_info.outbound < outbound_feature_supported)
1121 * XXX - multiple connections not yet supported
1122 */)
1123 previous_rcontact = NULL, ob->ob_previous = ob->ob_rcontact;
1124 else
1125 previous_rcontact = ob->ob_rcontact, ob->ob_previous = NULL;
1126
1127 if (ob->ob_previous)
1128 msg_header_replace_param(home, (void*)ob->ob_previous, "expires=0");
1129 }
1130 else {
1131 previous_previous = ob->ob_rcontact;
1132 previous_rcontact = NULL;
1133 previous_dcontact = ob->ob_dcontact;
1134 previous_via = ob->ob_via;
1135 }
1136
1137 ob->ob_contacts = 1;
1138
1139 ob->ob_rcontact = rcontact;
1140 ob->ob_dcontact = dcontact;
1141 ob->ob_via = v;
1142
1143 if (contact_uri_changed) {
1144 ob->ob_registering = 0;
1145 ob->ob_registered = 0;
1146 ob->ob_validated = 0;
1147 }
1148
1149 msg_header_free(home, (void *)previous_rcontact);
1150 msg_header_free(home, (void *)previous_previous);
1151 if (previous_dcontact != ob->ob_previous &&
1152 previous_dcontact != previous_rcontact &&
1153 previous_dcontact != previous_previous)
1154 msg_header_free(home, (void *)previous_dcontact);
1155 msg_header_free(home, (void *)previous_via);
1156
1157 return 0;
1158 }
1159
1160 /**Set new contact.
1161 *
1162 * @retval 0 when successful
1163 * @retval -1 error setting contact
1164 */
outbound_set_contact(outbound_t * ob,sip_contact_t const * application_contact,sip_via_t const * v,int terminating)1165 int outbound_set_contact(outbound_t *ob,
1166 sip_contact_t const *application_contact,
1167 sip_via_t const *v,
1168 int terminating)
1169 {
1170 su_home_t *home = ob->ob_home;
1171 sip_contact_t *rcontact = NULL, *dcontact = NULL, *previous = NULL;
1172 sip_contact_t *m1, *m2, *m3;
1173 int contact_uri_changed = 0;
1174
1175 m1 = ob->ob_rcontact;
1176 m2 = ob->ob_dcontact;
1177 m3 = ob->ob_previous;
1178
1179 if (terminating) {
1180 if (ob->ob_by_stack && application_contact == NULL)
1181 return 0;
1182
1183 if (ob->ob_contacts)
1184 previous = ob->ob_rcontact;
1185 }
1186 else if (application_contact) {
1187 rcontact = sip_contact_dup(home, application_contact);
1188
1189 if (!ob->ob_rcontact ||
1190 url_cmp_all(ob->ob_rcontact->m_url, application_contact->m_url)) {
1191 contact_uri_changed = 1;
1192 previous = ob->ob_contacts ? ob->ob_rcontact : NULL;
1193 }
1194 }
1195 else if (ob->ob_by_stack) {
1196 return 0; /* Xyzzy - nothing happens */
1197 }
1198 else if (v) {
1199 char const *tport = !v->v_next ? v->v_protocol : NULL;
1200 char reg_id_param[20];
1201
1202 dcontact = ob->ob_oo->oo_contact(ob->ob_owner, home, 1,
1203 v, tport, NULL);
1204 if (!dcontact)
1205 return -1;
1206
1207 if (ob->ob_instance && ob->ob_reg_id != 0)
1208 snprintf(reg_id_param, sizeof reg_id_param, ";reg-id=%u", ob->ob_reg_id);
1209
1210 rcontact = ob->ob_oo->oo_contact(ob->ob_owner, home, 0,
1211 v, v->v_protocol,
1212 ob->ob_instance, reg_id_param, NULL);
1213 if (!rcontact)
1214 return -1;
1215
1216 if (!ob->ob_rcontact ||
1217 url_cmp_all(ob->ob_rcontact->m_url, rcontact->m_url)) {
1218 contact_uri_changed = 1;
1219 previous = ob->ob_contacts ? ob->ob_rcontact : NULL;
1220 }
1221 }
1222
1223 ob->ob_by_stack = application_contact == NULL;
1224
1225 ob->ob_contacts = rcontact != NULL;
1226
1227 ob->ob_rcontact = rcontact;
1228 ob->ob_dcontact = dcontact;
1229 ob->ob_previous = previous;
1230
1231 if (contact_uri_changed) {
1232 ob->ob_registering = 0;
1233 ob->ob_registered = 0;
1234 ob->ob_validated = 0;
1235 ob->ob_once_validated = 0;
1236 }
1237
1238 if (m1 != previous)
1239 msg_header_free(home, (void *)m1);
1240 if (m2 != m1 && m2 != m3)
1241 msg_header_free(home, (void *)m2);
1242 msg_header_free(home, (void *)m3);
1243
1244 return 0;
1245 }
1246
outbound_dialog_contact(outbound_t const * ob)1247 sip_contact_t const *outbound_dialog_contact(outbound_t const *ob)
1248 {
1249 if (ob == NULL)
1250 return NULL;
1251 else if (ob->ob_gruu)
1252 return ob->ob_gruu;
1253 else
1254 return ob->ob_dcontact;
1255 }
1256
outbound_dialog_gruu(outbound_t const * ob)1257 sip_contact_t const *outbound_dialog_gruu(outbound_t const *ob)
1258 {
1259 return ob ? ob->ob_gruu : NULL;
1260 }
1261
1262 /* ---------------------------------------------------------------------- */
1263
1264
1265 static enum outbound_feature
feature_level(sip_t const * sip,char const * tag,int level)1266 feature_level(sip_t const *sip, char const *tag, int level)
1267 {
1268 if (sip_has_feature(sip->sip_require, tag))
1269 return outbound_feature_required;
1270 else if (sip_has_feature(sip->sip_supported, tag))
1271 return outbound_feature_supported;
1272 else if (sip_has_feature(sip->sip_unsupported, tag))
1273 return outbound_feature_unsupported;
1274 else
1275 return (enum outbound_feature)level;
1276 }
1277
1278
outbound_peer_info(outbound_t * ob,sip_t const * sip)1279 void outbound_peer_info(outbound_t *ob, sip_t const *sip)
1280 {
1281 if (sip == NULL) {
1282 ob->ob_info.outbound = outbound_feature_unsure;
1283 ob->ob_info.gruu = outbound_feature_unsure;
1284 ob->ob_info.pref = outbound_feature_unsure;
1285 return;
1286 }
1287
1288 ob->ob_info.outbound = feature_level(sip, "outbound", ob->ob_info.outbound);
1289 ob->ob_info.gruu = feature_level(sip, "gruu", ob->ob_info.gruu);
1290 ob->ob_info.pref = feature_level(sip, "pref", ob->ob_info.pref);
1291 }
1292