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