mangler: pkg free in case of errors
[sip-router] / src / modules / mangler / contact_ops.c
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
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
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
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
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
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
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
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);
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         /* dst_uri */
684         if (dst_uri && format.rcv_ip.s){
685                 dst_uri->len=4 /* sip: */ + format.rcv_ip.len;
686                 if (format.rcv_port.len){
687                         dst_uri->len+=1 /* : */+format.rcv_port.len;
688                 }
689                 if (format.rcv_proto.len){
690                         dst_uri->len+=TRANSPORT_PARAM_LEN+format.rcv_proto.len;
691                 }
692                 dst_uri->s=pkg_malloc(dst_uri->len);
693                 if (dst_uri->s==0){
694                         LOG(L_ERR,"ERROR: decode_contact: dst_uri: memory allocation"
695                                         " failed\n");
696                         dst_uri->len=0;
697                         pkg_free(result->s);
698                         result->s=0;
699                         result->len=0;
700                         return -4;
701                 }
702                 pos=dst_uri->s;
703                 memcpy(pos, SIP_SCH, SIP_SCH_LEN);
704                 pos+=SIP_SCH_LEN;
705                 memcpy(pos, format.rcv_ip.s, format.rcv_ip.len);
706                 pos+=format.rcv_ip.len;
707                 if (format.rcv_port.len){
708                         *pos=':';
709                         pos++;
710                         memcpy(pos, format.rcv_port.s, format.rcv_port.len);
711                         pos+=format.rcv_port.len;
712                 }
713                 if (format.rcv_proto.len){
714                         memcpy(pos, TRANSPORT_PARAM, TRANSPORT_PARAM_LEN);
715                         pos+=TRANSPORT_PARAM_LEN;
716                         memcpy(pos, format.rcv_proto.s, format.rcv_proto.len);
717                 }
718         }
719         return 0;
720 }
721