1 /*
2  * mangler module
3  *
4  * Copyright (C) 2001-2003 FhG Fokus
5  *
6  * This file is part of Kamailio, a free SIP server.
7  *
8  * Kamailio is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version
12  *
13  * Kamailio is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21  */
22 
23 #include "contact_ops.h"
24 #include "utils.h"
25 #include "common.h"
26 #include "../../core/mem/mem.h"
27 #include "../../core/data_lump.h"
28 #include "../../core/parser/hf.h"
29 #include "../../core/parser/parse_uri.h"
30 #include "../../core/parser/contact/parse_contact.h"
31 #include "../../core/ut.h"
32 #include "../../core/dset.h"
33 
34 #include <stdio.h>
35 #include <string.h>
36 
37 #define SIP_SCH	"sip:"
38 #define SIP_SCH_LEN	(sizeof(SIP_SCH)-1)
39 
40 
41 int
encode_contact(struct sip_msg * msg,char * encoding_prefix,char * public_ip)42 encode_contact (struct sip_msg *msg, char *encoding_prefix,char *public_ip)
43 {
44 
45 	contact_body_t *cb;
46 	contact_t *c;
47 	str* uri;
48 	str newUri;
49 	int res;
50 	char separator;
51 
52 
53 
54 	/*
55 	 * I have a list of contacts in contact->parsed which is of type contact_body_t
56 	 * inside i have a contact->parsed->contact which is the head of the list of contacts
57 	 * inside it is a
58 	 * str uri;
59 	 * struct contact *next;
60 	 * I just have to visit each uri and encode each uri according to a scheme
61 	 */
62 
63 	if ((msg->contact == NULL)&&((parse_headers(msg,HDR_CONTACT_F,0) == -1) ||
64 				(msg->contact == NULL) ))
65 		{
66 		LOG(L_ERR,"ERROR: encode_contact: no Contact header present\n");
67 		return -1;
68 		}
69 
70 
71 	separator = DEFAULT_SEPARATOR[0];
72 	if (contact_flds_separator != NULL)
73 		if (strlen(contact_flds_separator)>=1)
74 			separator = contact_flds_separator[0];
75 
76 	if (msg->contact->parsed == NULL) {
77 		if(parse_contact (msg->contact)<0) {
78 			LM_DBG("failed to parse contact\n");
79 		}
80 	}
81 	if (msg->contact->parsed != NULL)
82 	{
83 		cb = (contact_body_t *) msg->contact->parsed;
84 		c = cb->contacts;
85 		/* we visit each contact */
86 		if (c != NULL)
87 		{
88 			uri = &c->uri;
89 			res = encode_uri(msg, uri, encoding_prefix, public_ip,
90 								separator, &newUri);
91 
92 			if (res != 0)
93 				{
94 				LOG (L_ERR,"ERROR: encode_contact: Failed encoding contact.Code %d\n", res);
95 				return res;
96 				}
97 			else
98 				if (patch (msg, uri->s, uri->len, newUri.s, newUri.len) < 0)
99 				{
100 					LOG (L_ERR,"ERROR: encode_contact: lumping failed in mangling port \n");
101 					return -2;
102 				}
103 
104 			/* encoding next contacts too?*/
105 #ifdef ENCODE_ALL_CONTACTS
106 			while (c->next != NULL)
107 			{
108 				c = c->next;
109 				uri = &c->uri;
110 
111 				res = encode_uri (msg, uri, encoding_prefix, public_ip,
112 									separator, &newUri);
113 				if (res != 0)
114 					{
115 					LOG(L_ERR,"ERROR: encode_contact: Failed encode_uri.Code %d\n",res);
116 #ifdef STRICT_CHECK
117 				return res;
118 #endif
119 					}
120 				else
121 				if (patch (msg, uri->s, uri->len, newUri.s, newUri.len)< 0)
122 				{
123 					LOG (L_ERR,"ERROR: encode_contact: lumping failed in mangling port \n");
124 					return -3;
125 				}
126 			} /* while */
127 #endif /* ENCODE_ALL_CONTACTS */
128 		} /* if c != NULL */
129 
130 	} /* end if */
131 	else /* after parsing still NULL */
132 		{
133 			LOG(L_ERR,"ERROR: encode_contact: Unable to parse Contact header\n");
134 #ifdef EXTRA_DEBUG
135     			printf("ERROR: encode_contact: Unable to parse Contact header\n");
136 #endif
137 			return -4;
138 		}
139 #ifdef EXTRA_DEBUG
140 	fprintf (stdout,"---END--------ENCODE CONTACT-----------------\n");
141 #endif
142 	return 1;
143 }
144 
145 int
decode_contact(struct sip_msg * msg,char * unused1,char * unused2)146 decode_contact (struct sip_msg *msg,char *unused1,char *unused2)
147 {
148 
149 	str* uri;
150 	str newUri;
151 	str dst_uri;
152 	char separator;
153 	int res;
154 
155 
156 	separator = DEFAULT_SEPARATOR[0];
157 	if (contact_flds_separator != NULL)
158 		if (strlen(contact_flds_separator)>=1)
159 			separator = contact_flds_separator[0];
160 
161 	if ((msg->new_uri.s == NULL) || (msg->new_uri.len == 0)) {
162 		uri = &msg->first_line.u.request.uri;
163 	}else{
164 		uri = &msg->new_uri;
165 	}
166 
167 	res = decode_uri (uri, separator, &newUri, &dst_uri);
168 
169 	if (res != 0) {
170 			LOG (L_ERR,"ERROR: decode_contact:Failed decoding contact."
171 						"Code %d\n", res);
172 			return res;
173 	} else {
174 		/* we do not modify the original first line */
175 		if (msg->new_uri.s)
176 			pkg_free(msg->new_uri.s);
177 		msg->new_uri = newUri;
178 		msg->parsed_uri_ok=0;
179 		msg->dst_uri = dst_uri;
180 		ruri_mark_new();
181 	}
182 	return 1;
183 }
184 
185 int
decode_contact_header(struct sip_msg * msg,char * unused1,char * unused2)186 decode_contact_header (struct sip_msg *msg,char *unused1,char *unused2)
187 {
188 
189 	contact_body_t *cb;
190 	contact_t *c;
191 	str* uri;
192 	str newUri;
193 	char separator;
194 	int res;
195 
196 	if ((msg->contact == NULL)&&((parse_headers(msg,HDR_CONTACT_F,0) == -1) ||
197 				(msg->contact== NULL) ))
198 		{
199 		LOG(L_ERR,"ERROR: decode_contact_header: no Contact header present\n");
200 		return -1;
201 		}
202 
203 	separator = DEFAULT_SEPARATOR[0];
204 	if (contact_flds_separator != NULL)
205 		if (strlen(contact_flds_separator)>=1)
206 			separator = contact_flds_separator[0];
207 
208 	if (msg->contact->parsed == NULL) {
209 		if(parse_contact (msg->contact)<0) {
210 			LM_DBG("failed to parse contact\n");
211 		}
212 	}
213 	if (msg->contact->parsed != NULL)
214 	{
215 		cb = (contact_body_t *) msg->contact->parsed;
216 		c = cb->contacts;
217 		// we visit each contact
218 	 if (c != NULL)
219 	  {
220 		uri = &c->uri;
221 
222 		res = decode_uri (uri, separator, &newUri, 0);
223 		if (res != 0)
224 		{
225 			LOG (L_ERR,"ERROR: decode_contact_header:Failed decoding contact.Code %d\n", res);
226 #ifdef STRICT_CHECK
227 				return res;
228 #endif
229 		}
230 		else
231 		if (patch (msg, uri->s, uri->len, newUri.s, newUri.len) < 0)
232 		{
233 			LOG (L_ERR,"ERROR: decode_contact:lumping failed in mangling port \n");
234 			return -2;
235 		}
236 
237 #ifdef DECODE_ALL_CONTACTS
238 		while (c->next != NULL)
239 		{
240 			c = c->next;
241 			uri = &c->uri;
242 
243 			res = decode_uri (uri, separator, &newUri, 0);
244 			if (res != 0)
245 				{
246 				LOG (L_ERR,"ERROR: decode_contact: Failed decoding contact.Code %d\n",res);
247 #ifdef STRICT_CHECK
248 				return res;
249 #endif
250 				}
251 			else
252 			if (patch (msg, uri->s, uri->len, newUri.s, newUri.len) < 0)
253 			{
254 				LOG (L_ERR,"ERROR: decode_contact:lumping failed in mangling port \n");
255 				return -3;
256 			}
257 		} // end while
258 #endif
259 	   } // if c!= NULL
260 	} // end if
261 	else // after parsing still NULL
262 		{
263 			LOG(L_ERR,"ERROR: decode_contact: Unable to parse Contact header\n");
264 			return -4;
265 		}
266 	return 1;
267 }
268 
269 
270 static str	s_tcp  = STR_STATIC_INIT("tcp");
271 static str	s_tls  = STR_STATIC_INIT("tls");
272 static str	s_sctp = STR_STATIC_INIT("sctp");
273 
274 
275 
276 int
encode2format(struct sip_msg * msg,str * uri,struct uri_format * format)277 encode2format (struct sip_msg* msg, str* uri, struct uri_format *format)
278 {
279 	int foo;
280 	char *string, *pos, *start, *end;
281 	struct sip_uri sipUri;
282 	int scheme_len;
283 
284 
285 	if (uri->s == NULL)
286 		return -1;
287 	string = uri->s;
288 
289 
290 	pos = q_memchr (string, '<', uri->len);
291 	if (pos != NULL)	/* we are only interested of chars inside <> */
292 	{
293 		start = q_memchr (string, ':', uri->len);
294 		if (start == NULL)	return -2;
295 		if (start - pos < 4) return -3;
296 		if ((*(start-1)|0x20)=='s' && (start-pos)>4)
297 			/* if it ends in s: it is a sips or tels uri */
298 			scheme_len=4;
299 		else
300 			scheme_len=3;
301 		start-=scheme_len;
302 		end = strchr (start, '>');
303 		if (end == NULL)
304 			return -4;	/* must be a match to < */
305 	}
306 	else			/* we do not have  <> */
307 	{
308 		pos=string;
309 		start = q_memchr (string, ':', uri->len);
310 		if (start == NULL)
311 			return -5;
312 		if (start - pos < 3)
313 			return -6;
314 		if ((*(start-1)|0x20)=='s' && (start-pos)>3)
315 			/* if it ends in s: it is a sips or tels uri */
316 			scheme_len=4;
317 		else
318 			scheme_len=3;
319 		start = start - scheme_len;
320 		end = string + uri->len;
321 	}
322 	memset(format,0,sizeof(struct uri_format));
323 	format->first = start - string + scheme_len+1 /* ':' */;
324 	format->second = end - string;
325 	/* --------------------------testing ------------------------------- */
326 	/* sip:gva@pass@10.0.0.1;;transport=udp>;expires=2 INCORECT BEHAVIOR OF parse_uri,myfunction works good */
327 	foo = parse_uri (start, end - start, &sipUri);
328 	if (foo != 0)
329 	{
330 		LOG(L_ERR,"ERROR: encode2format: parse_uri failed on [%.*s]."
331 				"Code %d \n", uri->len, uri->s, foo);
332 		return foo-10;
333 	}
334 
335 
336 	format->username = sipUri.user;
337 	format->password = sipUri.passwd;
338 	format->ip = sipUri.host;
339 	format->port = sipUri.port;
340 	format->protocol = sipUri.transport_val;
341 	format->transport=sipUri.transport; /* the whole transport header */
342 	format->rest.s = sipUri.port.s?(sipUri.port.s+sipUri.port.len):
343 						(sipUri.host.s+sipUri.host.len);
344 	format->rest.len = (int)(end-format->rest.s);
345 	format->rcv_ip.s=ip_addr2a(&msg->rcv.src_ip);
346 	format->rcv_ip.len=strlen(format->rcv_ip.s);
347 	if (msg->rcv.src_port!=SIP_PORT){
348 		format->rcv_port.s=
349 				int2str(msg->rcv.src_port, &format->rcv_port.len);
350 	}else{
351 		format->rcv_port.s=0;
352 		format->rcv_port.len=0;
353 	}
354 	if (msg->rcv.proto!=PROTO_UDP){
355 		switch(msg->rcv.proto){
356 			case PROTO_TCP:
357 				format->rcv_proto=s_tcp;
358 				break;
359 			case PROTO_TLS:
360 				format->rcv_proto=s_tls;
361 				break;
362 			case PROTO_SCTP:
363 				format->rcv_proto=s_sctp;
364 				break;
365 			default:
366 				BUG("unknown proto %d\n", msg->rcv.proto);
367 		}
368 	}else{
369 		format->rcv_proto.s=0;
370 		format->rcv_proto.len=0;
371 	}
372 
373 #ifdef EXTRA_DEBUG
374 	fprintf (stdout, "transport=[%.*s] transportval=[%.*s]\n", sipUri.transport.len,sipUri.transport.s,sipUri.transport_val.len,sipUri.transport_val.s);
375 	fprintf(stdout,"First %d,second %d\n",format->first,format->second);
376 	#endif
377 
378 	return 0;
379 
380 }
381 
382 
383 int
encode_uri(struct sip_msg * msg,str * uri,char * encoding_prefix,char * public_ip,char separator,str * result)384 encode_uri (struct sip_msg* msg, str* uri, char *encoding_prefix,
385 				char *public_ip,char separator, str * result)
386 {
387 	struct uri_format format;
388 	char *pos;
389 	int foo,res;
390 
391 
392 	result->s = NULL;
393 	result->len = 0;
394 	if (uri->len <= 1)
395 		return -1;	/* no contact or an invalid one */
396 	if (public_ip == NULL)
397 		{
398 			LOG(L_ERR,"ERROR: encode_uri: Invalid NULL value for public_ip parameter\n");
399 			return -2;
400 		}
401 	foo = encode2format (msg, uri, &format);
402 	if (foo < 0)
403 		{
404 		LOG(L_ERR,"ERROR: encode_uri: Unable to encode Contact URI"
405 				" [%.*s].Return code %d\n",uri->len, uri->s, foo);
406 		return foo - 20;
407 		}
408 
409 	/* a complete uri would be sip:username@ip:port;transport=protocol goes to
410 	 * sip:enc_pref*username*ip*port*protocol@public_ip
411 	 */
412 
413 	foo = 1;		/*strlen(separator); */
414 	result->len = format.first + uri->s+uri->len - format.rest.s +
415 		strlen (encoding_prefix) + foo +
416 		format.username.len + foo +
417 		format.password.len + foo +
418 		format.ip.len + foo + format.port.len + foo +
419 		format.protocol.len + foo + format.rcv_ip.len + foo +
420 		format.rcv_port.len + foo + format.rcv_proto.len +
421 		1 + strlen (public_ip);
422 	/* adding one comes from @ */
423 	result->s = pkg_malloc (result->len);
424 	pos = result->s;
425 	if (pos == NULL)
426 		{
427 			LOG(L_ERR,"ERROR: encode_uri:Unable to alloc memory\n");
428 			return -3;
429 		}
430 
431 	res = snprintf(pos,result->len,"%.*s%s%c%.*s%c%.*s%c%.*s%c%.*s%c%.*s%c"
432 									"%.*s%c%.*s%c%.*s@",
433 			format.first, uri->s,encoding_prefix,separator,
434 			format.username.len,format.username.s,separator,
435 			format.password.len,format.password.s,
436 			separator,format.ip.len,format.ip.s,separator,format.port.len,
437 			format.port.s,separator,format.protocol.len,format.protocol.s,
438 			separator, format.rcv_ip.len, format.rcv_ip.s, separator,
439 			format.rcv_port.len, format.rcv_port.s, separator,
440 			format.rcv_proto.len, format.rcv_proto.s
441 			);
442 
443 	if ((res < 0 )||(res>result->len))
444 		{
445 			LOG(L_ERR,"ERROR: encode_uri: Unable to construct new uri.\n");
446 			if (result->s != NULL) pkg_free(result->s);
447 			return -4;
448 		}
449 	pos = pos + res ;/* overwriting the \0 from snprintf */
450 	memcpy (pos, public_ip, strlen (public_ip));
451 	pos = pos + strlen (public_ip);
452 	/* copy the rest of the parameters and the rest of uri line*/
453 	memcpy (pos, format.rest.s, uri->s+uri->len - format.rest.s);
454 	/*memcpy (pos, uri.s + format.second, uri.len - format.second);*/
455 
456 	/* Because called parse_uri format contains pointers to the inside of msg,
457 	 *  must not deallocate */
458 
459 	return 0;
460 }
461 
462 
463 int
decode2format(str * uri,char separator,struct uri_format * format)464 decode2format (str* uri, char separator, struct uri_format *format)
465 {
466 	char *start, *end, *pos,*lastpos;
467 	str tmp;
468 	enum {EX_PREFIX=0,EX_USER,EX_PASS,EX_IP,EX_PORT,EX_PROT, EX_RCVIP,
469 			EX_RCVPORT, EX_RCVPROTO, EX_FINAL} state;
470 
471 	memset (format, 0, sizeof(struct uri_format));
472 
473 	if (uri->s == NULL)
474 		{
475 		LOG(L_ERR,"ERROR: decode2format: Invalid parameter uri.It is NULL\n");
476 		return -1;
477 		}
478 	/* sip:enc_pref*username*password*ip*port*protocol@public_ip */
479 
480 	start = q_memchr (uri->s, ':', uri->len);
481 	if (start == NULL)
482 	{
483 		LOG(L_ERR,"ERROR: decode2format: Invalid SIP uri.Missing :\n");
484 		return -2;
485 	}			/* invalid uri */
486 	start = start + 1;
487 	if (start >= (uri->s+uri->len)){
488 		LOG(L_ERR, "ERROR: decode2format> Invalid sip uri: too short: %.*s\n",
489 				uri->len, uri->s);
490 		return -2;
491 	}
492 	format->first = start - uri->s;
493 
494 	/* start */
495 
496 	end = q_memchr(start,'@',uri->len-(start-uri->s));
497 	if (end == NULL)
498 		{
499 		LOG(L_ERR,"ERROR: decode2format: Invalid SIP uri.Missing @\n");
500 		return -3;/* no host address found */
501 		}
502 
503 #ifdef EXTRA_DEBUG
504 		fprintf (stdout, "Decoding %.*s\n",(int)(long)(end-start), start);
505 #endif
506 
507 	state = EX_PREFIX;
508 	lastpos = start;
509 
510 	for (pos = start;pos<end;pos++)
511 		{
512 			if (*pos == separator)
513 				{
514 					/* we copy between lastpos and pos */
515 					tmp.len = pos - lastpos;
516 					if (tmp.len>0) tmp.s = lastpos;
517 						else tmp.s = NULL;
518 					switch (state)
519 						{
520 							case EX_PREFIX: state = EX_USER;break;
521 							case EX_USER:format->username = tmp;state = EX_PASS;break;
522 							case EX_PASS:format->password = tmp;state = EX_IP;break;
523 							case EX_IP:format->ip = tmp;state = EX_PORT;break;
524 							case EX_PORT:format->port = tmp;state = EX_PROT;break;
525 							case EX_PROT:
526 										 format->protocol=tmp;
527 										 state=EX_RCVIP;
528 										 break;
529 							case EX_RCVIP:
530 										 format->rcv_ip=tmp;
531 										 state=EX_RCVPORT;
532 										 break;
533 							case EX_RCVPORT:
534 										 format->rcv_port=tmp;
535 										 state=EX_RCVPROTO;
536 										 break;
537 							default:
538 								{
539 								/* this should not happen, we should find @ not separator */
540 								return -4;
541 								break;
542 								}
543 						}
544 
545 					lastpos = pos+1;
546 
547 				}
548 			else
549 			if (((*pos) == '>')||(*pos == ';'))
550 				{
551 				/* invalid chars inside username part */
552 				return -5;
553 				}
554 		}
555 
556 
557 	/* we must be in state EX_RCVPROTO and protocol is between lastpos and
558 	 * end@ */
559 	if (state != EX_RCVPROTO) return -6;
560 	format->rcv_proto.len = end - lastpos;
561 	if (format->rcv_proto.len>0) format->rcv_proto.s = lastpos;
562 	/* I should check perhaps that 	after @ there is something */
563 
564 	/* looking for the end of public ip */
565 	start = end;/*we are now at @ */
566 	for(pos = start;pos<(uri->s+uri->len);pos++)
567 		{
568 			if ((*pos == ';')||(*pos == '>'))
569 				{
570 				/* found end */
571 				format->second = pos - uri->s;
572 				return 0;
573 				}
574 		}
575 	/* if we are here we did not find > or ; */
576 	format->second = uri->len;
577 	return 0;
578 
579 }
580 
581 
582 int
decode_uri(str * uri,char separator,str * result,str * dst_uri)583 decode_uri (str* uri, char separator, str * result, str* dst_uri)
584 {
585 	char *pos;
586 	struct uri_format format;
587 	int foo;
588 
589 	result->s = NULL;
590 	result->len = 0;
591 	if (dst_uri){
592 		dst_uri->s=0;
593 		dst_uri->len=0;
594 	}
595 
596 	if ((uri->len <= 0) || (uri->s == NULL))
597 		{
598 		LOG(L_ERR,"ERROR: decode_uri: Invalid value for uri\n");
599 		return -1;
600 		}
601 
602 	foo = decode2format (uri, separator, &format);
603 	if (foo < 0)
604 		{
605 		LOG(L_ERR,"ERROR: decode_uri: Error decoding Contact uri .Error code %d\n",foo);
606 		return foo - 20;
607 		}
608 	/* sanity check */
609 	if (format.ip.len <= 0)
610 		{
611 			LOG(L_ERR,"ERROR: decode_uri: Unable to decode host address \n");
612 			return -2;/* should I quit or ignore ? */
613 		}
614 
615 	if ((format.password.len > 0) && (format.username.len <= 0))
616 		{
617 			LOG(L_ERR,"ERROR: decode_uri: Password decoded but no username available\n");
618 			return -3;
619 		}
620 
621 	/* a complete uri would be sip:username:password@ip:port;transport=protocol goes to
622 	 * sip:enc_pref#username#password#ip#port#protocol@public_ip
623 	 */
624 	result->len = format.first + (uri->len - format.second);	/* not NULL terminated */
625 	if (format.username.len > 0) result->len += format.username.len + 1;	//: or @
626 	if (format.password.len > 0) result->len += format.password.len + 1;	//@
627 
628 	/* if (format.ip.len > 0) */	     result->len += format.ip.len;
629 
630 	if (format.port.len > 0)     result->len += 1 + format.port.len;	//:
631 	if (format.protocol.len > 0) result->len += 1 + 10 + format.protocol.len;	//;transport=
632 
633 	/* adding one comes from * */
634 	result->s = pkg_malloc (result->len + 1); /* NULL termination */
635 	if (result->s == NULL)
636 		{
637 			LOG(L_ERR,"ERROR: decode_contact: Unable to allocate memory\n");
638 			return -4;
639 		}
640 	pos = result->s;
641 	memcpy (pos, uri->s, format.first);	/* till sip: */
642 	pos = pos + format.first;
643 
644 	if (format.username.len > 0)
645 	{
646 		memcpy (pos, format.username.s, format.username.len);
647 		pos = pos + format.username.len;
648 		if (format.password.len > 0)
649 			memcpy (pos, ":", 1);
650 		else
651 			memcpy (pos, "@", 1);
652 		pos = pos + 1;
653 	}
654 	if (format.password.len > 0)
655 	{
656 		memcpy (pos, format.password.s, format.password.len);
657 		pos = pos + format.password.len;
658 		memcpy (pos, "@", 1);
659 		pos = pos + 1;
660 	}
661 	/* if (format.ip.len > 0) */
662 
663 		memcpy (pos, format.ip.s, format.ip.len);
664 		pos = pos + format.ip.len;
665 
666 	if (format.port.len > 0)
667 	{
668 		memcpy (pos, ":", 1);
669 		pos = pos + 1;
670 		memcpy (pos, format.port.s, format.port.len);
671 		pos = pos + format.port.len;
672 	}
673 	if (format.protocol.len > 0)
674 	{
675 		memcpy (pos, ";transport=", 11);
676 		pos = pos + 11;
677 		memcpy (pos, format.protocol.s, format.protocol.len);
678 		pos = pos + format.protocol.len;
679 	}
680 
681 	memcpy (pos, uri->s + format.second, uri->len - format.second);	/* till end: */
682 
683 	result->s[result->len] = '\0';
684 
685 	/* dst_uri */
686 	if (dst_uri && format.rcv_ip.s){
687 		dst_uri->len=4 /* sip: */ + format.rcv_ip.len;
688 		if (format.rcv_port.len){
689 			dst_uri->len+=1 /* : */+format.rcv_port.len;
690 		}
691 		if (format.rcv_proto.len){
692 			dst_uri->len+=TRANSPORT_PARAM_LEN+format.rcv_proto.len;
693 		}
694 		dst_uri->s=pkg_malloc(dst_uri->len);
695 		if (dst_uri->s==0){
696 			LOG(L_ERR,"ERROR: decode_contact: dst_uri: memory allocation"
697 					" failed\n");
698 			dst_uri->len=0;
699 			pkg_free(result->s);
700 			result->s=0;
701 			result->len=0;
702 			return -4;
703 		}
704 		pos=dst_uri->s;
705 		memcpy(pos, SIP_SCH, SIP_SCH_LEN);
706 		pos+=SIP_SCH_LEN;
707 		memcpy(pos, format.rcv_ip.s, format.rcv_ip.len);
708 		pos+=format.rcv_ip.len;
709 		if (format.rcv_port.len){
710 			*pos=':';
711 			pos++;
712 			memcpy(pos, format.rcv_port.s, format.rcv_port.len);
713 			pos+=format.rcv_port.len;
714 		}
715 		if (format.rcv_proto.len){
716 			memcpy(pos, TRANSPORT_PARAM, TRANSPORT_PARAM_LEN);
717 			pos+=TRANSPORT_PARAM_LEN;
718 			memcpy(pos, format.rcv_proto.s, format.rcv_proto.len);
719 		}
720 	}
721 	return 0;
722 }
723 
724