b76c659ec9b836357f101e1dd08c12a0edb57b29
[sip-router] / modules / tm / t_msgbuilder.c
1 /*
2  * $Id$
3  *
4  * message printing
5  *
6  * Copyright (C) 2001-2003 FhG Fokus
7  *
8  * This file is part of ser, a free SIP server.
9  *
10  * ser is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version
14  *
15  * For a license to use the ser software under conditions
16  * other than those described here, or to purchase support for this
17  * software, please contact iptel.org by e-mail at the following addresses:
18  *    info@iptel.org
19  *
20  * ser is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License 
26  * along with this program; if not, write to the Free Software 
27  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
28  *
29  *
30  * History:
31  * ----------
32  * 2003-01-27  next baby-step to removing ZT - PRESERVE_ZT (jiri)
33  * 2003-02-13  build_uac_request uses proto (andrei)
34  * 2003-02-28  scratchpad compatibility abandoned (jiri)
35  * 2003-04-14  build_local no longer checks reply status as it
36  *             is now called before reply status is updated to
37  *             avoid late ACK sending (jiri)
38  * 2003-10-02  added via_builder set host/port support (andrei)
39  * 2004-02-11  FIFO/CANCEL + alignments (hash=f(callid,cseq)) (uli+jiri)
40  * 2004-02-13: t->is_invite and t->local replaced with flags (bogdan)
41  * 2006-04-21  build_uac_req, assemble_via use struct dest_info now;
42  *              uri2sock replaced with uri2dst (andrei)
43  * 2006-08-11  build_dlg_ack: use the first dns ip for which a send_sock
44  *              is found (andrei)
45  * 2007-03-15  build_dls_ack: removed next_hop and replaced by dst to avoid
46  *               resolving nexthop twice (andrei)
47  * 2007-05-28: build_local_reparse() is introdued: it uses the outgoing
48  *             INVITE as a source to construct a CANCEL or ACK (Miklos)
49  */
50
51 #include "defs.h"
52
53 #ifdef EXTRA_DEBUG
54 #include <assert.h>
55 #endif
56 #include "../../comp_defs.h"
57 #include "../../hash_func.h"
58 #include "../../globals.h"
59 #include "t_funcs.h"
60 #include "../../dprint.h"
61 #include "../../config.h"
62 #include "../../parser/parser_f.h"
63 #include "../../parser/parse_to.h"
64 #include "../../ut.h"
65 #include "../../parser/msg_parser.h"
66 #include "../../parser/contact/parse_contact.h"
67 #include "lw_parser.h"
68 #include "t_msgbuilder.h"
69 #include "uac.h"
70 #ifdef USE_DNS_FAILOVER
71 #include "../../dns_cache.h"
72 #include "../../cfg_core.h" /* cfg_get(core, core_cfg, use_dns_failover) */
73 #endif
74
75 /* convenience macros */
76 #define memapp(_d,_s,_len) \
77         do{\
78                 memcpy((_d),(_s),(_len));\
79                 (_d) += (_len);\
80         }while(0)
81
82
83 /* Build a local request based on a previous request; main
84    customers of this function are local ACK and local CANCEL
85  */
86 char *build_local(struct cell *Trans,unsigned int branch,
87         unsigned int *len, char *method, int method_len, str *to)
88 {
89         char                *cancel_buf, *p, *via;
90         unsigned int         via_len;
91         struct hdr_field    *hdr;
92         char branch_buf[MAX_BRANCH_PARAM_LEN];
93         int branch_len;
94         str branch_str;
95         str via_id;
96         struct hostport hp;
97
98         /* init */
99         via_id.s=0;
100         via_id.len=0;
101
102         /* method, separators, version: "CANCEL sip:p2@iptel.org SIP/2.0" */
103         *len=SIP_VERSION_LEN + method_len + 2 /* spaces */ + CRLF_LEN;
104         *len+=Trans->uac[branch].uri.len;
105
106         /*via*/
107         if (!t_calc_branch(Trans,  branch, 
108                 branch_buf, &branch_len ))
109                 goto error;
110         branch_str.s=branch_buf;
111         branch_str.len=branch_len;
112         set_hostport(&hp, (is_local(Trans))?0:(Trans->uas.request));
113 #ifdef USE_TCP
114         if (!is_local(Trans) && ((Trans->uas.request->rcv.proto==PROTO_TCP)
115 #ifdef USE_TLS
116                                 || (Trans->uas.request->rcv.proto==PROTO_TLS)
117 #endif /* USE_TLS */
118                 )){
119                 if ((via_id.s=id_builder(Trans->uas.request,
120                                                                         (unsigned int*)&via_id.len))==0){
121                         LOG(L_ERR, "ERROR: build_local: id builder failed\n");
122                         /* try to continue without id */
123                 }
124         }
125 #endif /* USE_TCP */
126         via=via_builder(&via_len, &Trans->uac[branch].request.dst,
127                 &branch_str, via_id.s?&via_id:0 , &hp );
128         
129         /* via_id.s not needed anylonger => free it */
130         if (via_id.s){
131                 pkg_free(via_id.s);
132                 via_id.s=0;
133                 via_id.len=0;
134         }
135         
136         if (!via)
137         {
138                 LOG(L_ERR, "ERROR: build_local: "
139                         "no via header got from builder\n");
140                 goto error;
141         }
142         *len+= via_len;
143         /*headers*/
144         *len+=Trans->from.len+Trans->callid.len+to->len+
145                 +Trans->cseq_n.len+1+method_len+CRLF_LEN; 
146
147
148         /* copy'n'paste Route headers */
149         if (!is_local(Trans)) {
150                 for ( hdr=Trans->uas.request->headers ; hdr ; hdr=hdr->next )
151                          if (hdr->type==HDR_ROUTE_T)
152                                 *len+=hdr->len;
153         }
154
155         /* User Agent */
156         if (server_signature) {
157                 *len += user_agent_hdr.len + CRLF_LEN;
158         }
159         /* Content Length, EoM */
160         *len+=CONTENT_LENGTH_LEN+1 + CRLF_LEN + CRLF_LEN;
161
162         cancel_buf=shm_malloc( *len+1 );
163         if (!cancel_buf)
164         {
165                 LOG(L_ERR, "ERROR: build_local: cannot allocate memory\n");
166                 goto error01;
167         }
168         p = cancel_buf;
169
170         append_str( p, method, method_len );
171         append_str( p, " ", 1 );
172         append_str( p, Trans->uac[branch].uri.s, Trans->uac[branch].uri.len);
173         append_str( p, " " SIP_VERSION CRLF, 1+SIP_VERSION_LEN+CRLF_LEN );
174
175         /* insert our via */
176         append_str(p,via,via_len);
177
178         /*other headers*/
179         append_str( p, Trans->from.s, Trans->from.len );
180         append_str( p, Trans->callid.s, Trans->callid.len );
181         append_str( p, to->s, to->len );
182
183         append_str( p, Trans->cseq_n.s, Trans->cseq_n.len );
184         append_str( p, " ", 1 );
185         append_str( p, method, method_len );
186         append_str( p, CRLF, CRLF_LEN );
187
188         if (!is_local(Trans))  {
189                 for ( hdr=Trans->uas.request->headers ; hdr ; hdr=hdr->next )
190                         if(hdr->type==HDR_ROUTE_T) {
191                                 append_str(p, hdr->name.s, hdr->len );
192                         }
193         }
194
195         /* User Agent header */
196         if (server_signature) {
197                 append_str(p, user_agent_hdr.s, user_agent_hdr.len );
198                 append_str(p, CRLF, CRLF_LEN );
199         }
200         /* Content Length, EoM */
201         append_str(p, CONTENT_LENGTH "0" CRLF CRLF ,
202                 CONTENT_LENGTH_LEN+1 + CRLF_LEN + CRLF_LEN);
203         *p=0;
204
205         pkg_free(via);
206         return cancel_buf;
207 error01:
208         pkg_free(via);
209 error:
210         return NULL;
211 }
212
213 /* Re-parsing version of build_local() function:
214  * it builds a local CANCEL or ACK (for non-200 response) request based on
215  * the previous INVITE which was sent out.
216  *
217  * Can not be used to build other type of requests!
218  */
219 char *build_local_reparse(struct cell *Trans,unsigned int branch,
220         unsigned int *len, char *method, int method_len, str *to)
221 {
222         char    *invite_buf, *invite_buf_end;
223         char    *cancel_buf;
224         char    *s, *s1, *d;    /* source and destination buffers */
225         short   invite_len;
226         enum _hdr_types_t       hf_type;
227         int     first_via, to_len;
228
229         invite_buf = Trans->uac[branch].request.buffer;
230         invite_len = Trans->uac[branch].request.buffer_len;
231
232         if (!invite_buf || !invite_len) {
233                 LOG(L_ERR, "ERROR: build_local_reparse: INVITE is missing\n");
234                 goto error;
235         }
236         if ((*invite_buf != 'I') && (*invite_buf != 'i')) {
237                 LOG(L_ERR, "ERROR: build_local_reparse: trying to call build_local_reparse() for a non-INVITE request?\n");
238                 goto error;
239         }
240         invite_buf_end = invite_buf + invite_len;
241         s = invite_buf;
242
243         /* Allocate memory for the new message.
244         The new request will be smaller than the INVITE, so the same size is enough.
245         I just extend it with the length of new To HF to be sure.
246         Ugly, but we avoid lots of checks and memory allocations this way */
247         to_len = to ? to->len : 0;
248         cancel_buf = shm_malloc(sizeof(char)*(invite_len + to_len));
249         if (!cancel_buf)
250         {
251                 LOG(L_ERR, "ERROR: build_local_reparse: cannot allocate shared memory\n");
252                 goto error;
253         }
254         d = cancel_buf;
255
256         /* method name + space */
257         append_str(d, method, method_len);
258         *d = ' ';
259         d++;
260         /* skip "INVITE " and copy the rest of the line including CRLF */
261         s += 7;
262         s1 = s;
263         s = eat_line(s, invite_buf_end - s);
264         append_str(d, s1, s - s1);
265
266         /* check every header field name,
267         we must exclude and modify some of the headers */
268         first_via = 1;
269         while (s < invite_buf_end) {
270                 s1 = s;
271                 if ((*s == '\n') || (*s == '\r')) {
272                         /* end of SIP msg */
273                         hf_type = HDR_EOH_T;
274                 } else {
275                         /* parse HF name */
276                         s = lw_get_hf_name(s, invite_buf_end,
277                                                 &hf_type);
278                 }
279
280                 switch(hf_type) {
281                         case HDR_CSEQ_T:
282                                 /* find the method name and replace it */
283                                 while ((s < invite_buf_end)
284                                         && ((*s == ':') || (*s == ' ') || (*s == '\t') || ((*s >= '0') && (*s <= '9')))
285                                         ) s++;
286                                 append_str(d, s1, s - s1);
287                                 append_str(d, method, method_len);
288                                 append_str(d, CRLF, CRLF_LEN);
289                                 s = lw_next_line(s, invite_buf_end);
290                                 break;
291
292                         case HDR_VIA_T:
293                                 s = lw_next_line(s, invite_buf_end);
294                                 if (first_via) {
295                                         /* copy hf */
296                                         append_str(d, s1, s - s1);
297                                         first_via = 0;
298                                 } /* else skip this line, we need olny the first via */
299                                 break;
300
301                         case HDR_TO_T:
302                                 if (to_len == 0) {
303                                         /* there is no To tag required, just copy paste the header */
304                                         s = lw_next_line(s, invite_buf_end);
305                                         append_str(d, s1, s - s1);
306                                 } else {
307                                         /* use the given To HF instead of the original one */
308                                         append_str(d, to->s, to->len);
309                                         /* move the pointer to the next line */
310                                         s = lw_next_line(s, invite_buf_end);
311                                 }
312                                 break;
313
314                         case HDR_FROM_T:
315                         case HDR_CALLID_T:
316                         case HDR_ROUTE_T:
317                         case HDR_MAXFORWARDS_T:
318                                 /* copy hf */
319                                 s = lw_next_line(s, invite_buf_end);
320                                 append_str(d, s1, s - s1);
321                                 break;
322
323                         case HDR_REQUIRE_T:
324                         case HDR_PROXYREQUIRE_T:
325                                 /* skip this line */
326                                 s = lw_next_line(s, invite_buf_end);
327                                 break;
328
329                         case HDR_CONTENTLENGTH_T:
330                                 /* copy hf name with 0 value */
331                                 append_str(d, s1, s - s1);
332                                 append_str(d, ": 0" CRLF, 3 + CRLF_LEN);
333                                 /* move the pointer to the next line */
334                                 s = lw_next_line(s, invite_buf_end);
335                                 break;
336
337                         case HDR_EOH_T:
338                                 /* end of SIP message found */
339                                 append_str(d, CRLF, CRLF_LEN);
340                                 *len = d - cancel_buf;
341                                 /* LOG(L_DBG, "DBG: build_local: %.*s\n", *len, cancel_buf); */
342                                 return cancel_buf;
343
344                         default:
345                                 s = lw_next_line(s, invite_buf_end);
346
347                                 if (cfg_get(tm, tm_cfg, ac_extra_hdrs).len
348                                 && (s1 + cfg_get(tm, tm_cfg, ac_extra_hdrs).len < invite_buf_end)
349                                 && (strncasecmp(s1,
350                                                 cfg_get(tm, tm_cfg, ac_extra_hdrs).s,
351                                                 cfg_get(tm, tm_cfg, ac_extra_hdrs).len) == 0)
352                                 ) {
353                                         append_str(d, s1, s - s1);
354                                 } /* else skip this line */
355                                 break;
356                 }
357         }
358
359         /* HDR_EOH_T was not found in the buffer, the message is corrupt */
360         LOG(L_ERR, "ERROR: build_local_reparse: HDR_EOH_T was not found\n");
361
362         shm_free(cancel_buf);
363 error:
364         LOG(L_ERR, "ERROR: build_local_reparse: cannot build %.*s request\n", method_len, method);
365         return NULL;
366
367 }
368
369
370 typedef struct rte {
371         rr_t* ptr;
372         /* 'ptr' above doesn't point to a mem chunk linked to a sip_msg, so it
373          * won't be free'd along with it => it must be free'd "manually" */
374         int free_rr;
375         struct rte* next;
376 } rte_t;
377
378          
379 static inline void free_rte_list(struct rte* list)
380 {
381         struct rte* ptr;
382         
383         while(list) {
384                 ptr = list;
385                 list = list->next;
386                 if (ptr->free_rr)
387                         free_rr(&ptr->ptr);
388                 pkg_free(ptr);
389         }
390 }
391
392
393 static inline int calc_routeset_len(struct rte* list, str* contact)
394 {
395         struct rte* ptr;
396         int ret;
397         
398         if (list || contact) {
399                 ret = ROUTE_PREFIX_LEN + CRLF_LEN;
400         } else {
401                 return 0;
402         }
403         
404         ptr = list;
405         while(ptr) {
406                 if (ptr != list) {
407                         ret += ROUTE_SEPARATOR_LEN;
408                 }
409                 ret += ptr->ptr->len;
410                 ptr = ptr->next;
411         }
412         
413         if (contact) {
414                 if (list) ret += ROUTE_SEPARATOR_LEN;
415                 ret += 2 + contact->len;
416         }
417         
418         return ret;
419 }
420
421
422      /*
423       * Print the route set
424       */
425 static inline char* print_rs(char* p, struct rte* list, str* contact)
426 {
427         struct rte* ptr;
428         
429         if (list || contact) {
430                 memapp(p, ROUTE_PREFIX, ROUTE_PREFIX_LEN);
431         } else {
432                 return p;
433         }
434         
435         ptr = list;
436         while(ptr) {
437                 if (ptr != list) {
438                         memapp(p, ROUTE_SEPARATOR, ROUTE_SEPARATOR_LEN);
439                 }
440                 
441                 memapp(p, ptr->ptr->nameaddr.name.s, ptr->ptr->len);
442                 ptr = ptr->next;
443         }
444         
445         if (contact) {
446                 if (list) memapp(p, ROUTE_SEPARATOR, ROUTE_SEPARATOR_LEN);
447                 *p++ = '<';
448                 append_str(p, contact->s, contact->len);
449                 *p++ = '>';
450         }
451         
452         memapp(p, CRLF, CRLF_LEN);
453         return p;
454 }
455
456
457      /*
458       * Parse Contact header field body and extract URI
459       * Does not parse headers !
460       */
461 static inline int get_contact_uri(struct sip_msg* msg, str* uri)
462 {
463         contact_t* c;
464         
465         uri->len = 0;
466         if (!msg->contact) return 1;
467         
468         if (parse_contact(msg->contact) < 0) {
469                 LOG(L_ERR, "get_contact_uri: Error while parsing Contact body\n");
470                 return -1;
471         }
472         
473         c = ((contact_body_t*)msg->contact->parsed)->contacts;
474         
475         if (!c) {
476                 LOG(L_ERR, "get_contact_uri: Empty body or * contact\n");
477                 return -2;
478         }
479         
480         *uri = c->uri;
481         return 0;
482 }
483
484 /**
485  * Extract route set from the message (out of Record-Route, if reply, OR
486  * Route, if request).
487  * The route set is returned into the "UAC-format" (keep order for Rs, reverse
488  * RRs).
489  */
490 static inline int get_uac_rs(sip_msg_t *msg, int is_req, struct rte **rtset)
491 {
492         struct hdr_field* ptr;
493         rr_t *p, *new_p;
494         struct rte *t, *head, *old_head;
495
496         head = 0;
497         for (ptr = is_req ? msg->route : msg->record_route; ptr; ptr = ptr->next) {
498                 switch (ptr->type) {
499                         case HDR_RECORDROUTE_T:
500                                 if (is_req)
501                                         continue;
502                                 break;
503                         case HDR_ROUTE_T:
504                                 if (! is_req)
505                                         continue;
506                                 break;
507                         default:
508                                 continue;
509                 }
510                 if (parse_rr(ptr) < 0) {
511                         ERR("failed to parse Record-/Route HF (%d).\n", ptr->type);
512                         goto err;
513                 }
514                         
515                 p = (rr_t*)ptr->parsed;
516                 while(p) {
517                         if (! (t = pkg_malloc(sizeof(struct rte)))) {
518                                 ERR("out of pkg mem (asked for: %d).\n",
519                                                 (int)sizeof(struct rte));
520                                 goto err;
521                         }
522                         if (is_req) {
523                                 /* in case of requests, the sip_msg structure is free'd before
524                                  * rte list is evaluated => must do a copy of it */
525                                 if (duplicate_rr(&new_p, p) < 0) {
526                                         pkg_free(t);
527                                         ERR("failed to duplicate RR");
528                                         goto err;
529                                 }
530                                 t->ptr = new_p;
531                         } else {
532                                 t->ptr = p;
533                         }
534                         t->free_rr = is_req;
535                         t->next = head;
536                         head = t;
537                         p = p->next;
538                 }
539         }
540
541         if (is_req) {
542                 /* harvesting the R/RR HF above inserts at head, which suites RRs (as
543                  * they must be reversed, anyway), but not Rs => reverse once more */
544                 old_head = head;
545                 head = 0;
546                 while (old_head) {
547                         t = old_head;
548                         old_head = old_head->next;
549                         t->next = head;
550                         head = t;
551                 }
552         }
553
554         *rtset = head;
555         return 0;
556 err:
557         free_rte_list(head);
558         return -1;
559 }
560
561
562 static inline unsigned short uri2port(const struct sip_uri *puri)
563 {
564         if (puri->port.s) {
565                 return puri->port_no;
566         } else switch (puri->type) {
567                 case SIP_URI_T:
568                 case TEL_URI_T:
569                         if (puri->transport_val.len == sizeof("TLS") - 1) {
570                                 unsigned trans;
571                                 trans = puri->transport_val.s[0] | 0x20; trans <<= 8;
572                                 trans |= puri->transport_val.s[1] | 0x20; trans <<= 8;
573                                 trans |= puri->transport_val.s[2] | 0x20;
574                                 if (trans == 0x746C73) /* t l s */
575                                         return SIPS_PORT;
576                         }
577                         return SIP_PORT;
578                 case SIPS_URI_T:
579                 case TELS_URI_T:
580                         return SIPS_PORT;
581                 default:
582                         BUG("unexpected URI type %d.\n", puri->type);
583         }
584         return 0;
585 }
586
587 /**
588  * Evaluate if next hop is a strict or loose router, by looking at the
589  * retr. buffer of the original INVITE.
590  * Assumes:
591  *      orig_inv is a parsed SIP message;
592  *      rtset is not NULL.
593  * @return:
594  *      F_RB_NH_LOOSE : next hop was loose router;
595  *      F_RB_NH_STRICT: nh is strict;
596  *      0 on error.
597  */
598 static unsigned long nhop_type(sip_msg_t *orig_inv, rte_t *rtset,
599                 const struct dest_info *dst_inv, str *contact)
600 {
601         struct sip_uri puri, topr_uri, lastr_uri, inv_ruri, cont_uri;
602         struct ip_addr *uri_ia;
603         union sockaddr_union uri_sau;
604         unsigned int uri_port, dst_port, inv_port, cont_port, lastr_port;
605         rte_t *last_r;
606 #ifdef TM_LOC_ACK_DO_REV_DNS
607         struct ip_addr ia;
608         struct hostent *he;
609         char **alias;
610 #endif
611
612 #define PARSE_URI(_str_, _uri_) \
613         do { \
614                 /* parse_uri() 0z the puri */ \
615                 if (parse_uri((_str_)->s, \
616                                 (_str_)->len, _uri_) < 0) { \
617                         ERR("failed to parse route body '%.*s'.\n", STR_FMT(_str_)); \
618                         return 0; \
619                 } \
620         } while (0)
621
622 #define HAS_LR(_rte_) \
623         ({ \
624                 PARSE_URI(&(_rte_)->ptr->nameaddr.uri, &puri); \
625                 puri.lr.s; \
626         })
627
628 #define URI_PORT(_puri_, _port) \
629         do { \
630                 if (! (_port = uri2port(_puri_))) \
631                         return 0; \
632         } while (0)
633
634         /* examine the easy/fast & positive cases foremost */
635
636         /* [1] check if 1st route lacks ;lr */
637         DEBUG("checking lack of ';lr' in 1st route.\n");
638         if (! HAS_LR(rtset))
639                 return F_RB_NH_STRICT;
640         topr_uri = puri; /* save 1st route's URI */
641
642         /* [2] check if last route shows ;lr */
643         DEBUG("checking presence of ';lr' in last route.\n");
644         for (last_r = rtset; last_r->next; last_r = last_r->next)
645                 /* scroll down to last route */
646                 ;
647         if (HAS_LR(last_r))
648                 return F_RB_NH_LOOSE;
649
650         /* [3] 1st route has ;lr -> check if the destination of original INV
651          * equals the address provided by this route; if does -> loose */
652         DEBUG("checking INVITE's destination against its first route.\n");
653         URI_PORT(&topr_uri, uri_port);
654         if (! (dst_port = su_getport((void *)&dst_inv->to)))
655                 return 0; /* not really expected */
656         if (dst_port != uri_port)
657                 return F_RB_NH_STRICT;
658         /* if 1st route contains an IP address, comparing it against .dst */
659         if ((uri_ia = str2ip(&topr_uri.host))
660 #ifdef USE_IPV6
661                         || (uri_ia = str2ip6(&topr_uri.host))
662 #endif
663                         ) {
664                 /* we have an IP address in route -> comparison can go swiftly */
665                 if (init_su(&uri_sau, uri_ia, uri_port) < 0)
666                         return 0; /* not really expected */
667                 if (su_cmp(&uri_sau, (void *)&dst_inv->to))
668                         /* ;lr and sent there */
669                         return F_RB_NH_LOOSE;
670                 else
671                         /* ;lr and NOT sent there (probably sent to RURI address) */
672                         return F_RB_NH_STRICT;
673         } else {
674                 /*if 1st route contains a name, rev resolve the .dst and compare*/
675                 INFO("Failed to decode string '%.*s' in route set element as IP "
676                                 "address. Trying name resolution.\n",STR_FMT(&topr_uri.host));
677
678         /* TODO: alternatively, rev name and compare against dest. IP.  */
679 #ifdef TM_LOC_ACK_DO_REV_DNS
680                 ia.af = 0;
681                 su2ip_addr(&ia, (void *)&dst_inv->to);
682                 if (! ia.af)
683                         return 0; /* not really expected */
684                 if ((he = rev_resolvehost(&ia))) {
685                         if ((strlen(he->h_name) == topr_uri.host.len) &&
686                                         (memcmp(he->h_name, topr_uri.host.s, 
687                                                         topr_uri.host.len) == 0))
688                                 return F_RB_NH_LOOSE;
689                         for (alias = he->h_aliases; *alias; alias ++)
690                                 if ((strlen(*alias) == topr_uri.host.len) &&
691                                                 (memcmp(*alias, topr_uri.host.s, 
692                                                                 topr_uri.host.len) == 0))
693                                         return F_RB_NH_LOOSE;
694                         return F_RB_NH_STRICT;
695                 } else {
696                         INFO("failed to resolve address '%s' to a name.\n", 
697                                         ip_addr2a(&ia));
698                 }
699 #endif
700         }
701
702         WARN("failed to establish with certainty the type of next hop; trying an"
703                         " educated guess.\n");
704
705         /* [4] compare (possibly updated) remote target to original RURI; if
706          * equal, a strict router's address wasn't filled in as RURI -> loose */
707         DEBUG("checking remote target against INVITE's RURI.\n");
708         PARSE_URI(contact, &cont_uri);
709         PARSE_URI(GET_RURI(orig_inv), &inv_ruri);
710         URI_PORT(&cont_uri, cont_port);
711         URI_PORT(&inv_ruri, inv_port);
712         if ((cont_port == inv_port) && (cont_uri.host.len == inv_ruri.host.len) &&
713                         (memcmp(cont_uri.host.s, inv_ruri.host.s, cont_uri.host.len) == 0))
714                 return F_RB_NH_LOOSE;
715
716         /* [5] compare (possibly updated) remote target to last route; if equal, 
717          * strict router's address might have been filled as RURI and remote
718          * target appended to route set -> strict */
719         DEBUG("checking remote target against INVITE's last route.\n");
720         PARSE_URI(&last_r->ptr->nameaddr.uri, &lastr_uri);
721         URI_PORT(&lastr_uri, lastr_port);
722         if ((cont_port == lastr_port) && 
723                         (cont_uri.host.len == lastr_uri.host.len) &&
724                         (memcmp(cont_uri.host.s, lastr_uri.host.s, 
725                                         lastr_uri.host.len) == 0))
726                 return F_RB_NH_STRICT;
727
728         WARN("failed to establish the type of next hop; assuming loose router.\n");
729         return F_RB_NH_LOOSE;
730
731 #undef PARSE_URI
732 #undef HAS_LR
733 #undef URI_PORT
734 }
735
736 /**
737  * Evaluates the routing elements in locally originated request or reply to
738  * locally originated request.
739  * If original INVITE was in-dialog (had to-tag), it uses the
740  * routes present there (b/c the 2xx for it does not have a RR set, normally).
741  * Otherwise, use the reply (b/c the INVITE does not have yet the complete 
742  * route set).
743  *
744  * @return: negative for failure; out params:
745  *  - list: route set;
746  *  - ruri: RURI to be used in ACK;
747  *  - nexthop: where to first send the ACK.
748  *
749  *  NOTE: assumes rpl's parsed to EOF!
750  *
751  */
752 static int eval_uac_routing(sip_msg_t *rpl, const struct retr_buf *inv_rb, 
753                 str* contact, struct rte **list, str *ruri, str *next_hop)
754 {
755         sip_msg_t orig_inv, *sipmsg; /* reparse original INVITE */
756         rte_t *t, *prev_t, *rtset = NULL;
757         int is_req;
758         struct sip_uri puri;
759         static size_t chklen;
760         int ret = -1;
761         
762         /* parse the retr. buffer */
763         memset(&orig_inv, 0, sizeof(struct sip_msg));
764         orig_inv.buf = inv_rb->buffer;
765         orig_inv.len = inv_rb->buffer_len;
766         DEBUG("reparsing retransmission buffer of original INVITE:\n%.*s\n",
767                         (int)orig_inv.len, orig_inv.buf);
768         if (parse_msg(orig_inv.buf, orig_inv.len, &orig_inv) != 0) {
769                 ERR("failed to parse retr buffer (weird!): \n%.*s\n",
770                                 (int)orig_inv.len, orig_inv.buf);
771                 return -1;
772         }
773
774         /* check if we need to look at request or reply */
775         if ((parse_headers(&orig_inv, HDR_TO_F, 0) < 0) || (! orig_inv.to)) {
776                 /* the bug is at message assembly */
777                 BUG("failed to parse INVITE retr. buffer and/or extract 'To' HF:"
778                                 "\n%.*s\n", (int)orig_inv.len, orig_inv.buf);
779                 goto end;
780         }
781         if (((struct to_body *)orig_inv.to->parsed)->tag_value.len) {
782                 DEBUG("building ACK for in-dialog INVITE (using RS in orig. INV.)\n");
783                 if (parse_headers(&orig_inv, HDR_EOH_F, 0) < 0) {
784                         BUG("failed to parse INVITE retr. buffer to EOH:"
785                                         "\n%.*s\n", (int)orig_inv.len, orig_inv.buf);
786                         goto end;
787                 }
788                 sipmsg = &orig_inv;
789                 is_req = 1;
790         } else {
791                 DEBUG("building ACK for out-of-dialog INVITE (using RS in RR set).\n");
792                 sipmsg = rpl;
793                 is_req = 0;
794         }
795
796         /* extract the route set */
797         if (get_uac_rs(sipmsg, is_req, &rtset) < 0) {
798                 ERR("failed to extract route set.\n");
799                 goto end;
800         }
801
802         if (! rtset) { /* No routes */
803                 *ruri = *contact;
804                 *next_hop = *contact;
805         } else if (! is_req) { /* out of dialog req. */
806                 if (parse_uri(rtset->ptr->nameaddr.uri.s, rtset->ptr->nameaddr.uri.len,
807                                 &puri) < 0) {
808                         ERR("failed to parse first route in set.\n");
809                         goto end;
810                 }
811                 
812                 if (puri.lr.s) { /* Next hop is loose router */
813                         *ruri = *contact;
814                         *next_hop = rtset->ptr->nameaddr.uri;
815                 } else { /* Next hop is strict router */
816                         *ruri = rtset->ptr->nameaddr.uri;
817                         *next_hop = *ruri;
818                         /* consume first route, b/c it will be put in RURI */
819                         t = rtset;
820                         rtset = rtset->next;
821                         pkg_free(t);
822                 }
823         } else {
824                 unsigned long route_flags = inv_rb->flags;
825                 DEBUG("UAC rb flags: 0x%x.\n", (unsigned int)route_flags);
826 eval_flags:
827                 switch (route_flags & (F_RB_NH_LOOSE|F_RB_NH_STRICT)) {
828                 case 0:
829                         WARN("calculate_hooks() not called when built the local UAC of "
830                                         "in-dialog request, or called with empty route set.\n");
831                         /* try to figure out what kind of hop is the next one
832                          * (strict/loose) by reading the original invite */
833                         if ((route_flags = nhop_type(&orig_inv, rtset, &inv_rb->dst, 
834                                         contact))) {
835                                 DEBUG("original request's next hop type evaluated to: 0x%x.\n",
836                                                 (unsigned int)route_flags);
837                                 goto eval_flags;
838                         } else {
839                                 ERR("failed to establish what kind of router the next "
840                                                 "hop is.\n");
841                                 goto end;
842                         }
843                         break;
844                 case F_RB_NH_LOOSE:
845                         *ruri = *contact;
846                         *next_hop = rtset->ptr->nameaddr.uri;
847                         break;
848                 case F_RB_NH_STRICT:
849                         /* find ptr to last route body that contains the (possibly) old 
850                          * remote target 
851                          */
852                         for (t = rtset, prev_t = t; t->next; prev_t = t, t = t->next)
853                                 ;
854                         if ((t->ptr->len == contact->len) && 
855                                         (memcmp(t->ptr->nameaddr.name.s, contact->s, 
856                                                         contact->len) == 0)){
857                                 /* the remote target didn't update -> keep the whole route set,
858                                  * including the last entry */
859                                 /* do nothing */
860                         } else {
861                                 /* trash last entry and replace with new remote target */
862                                 free_rte_list(t);
863                                 /* compact the rr_t struct along with rte. this way, free'ing
864                                  * it can be done along with rte chunk, independent of Route
865                                  * header parser's allocator (using pkg/shm) */
866                                 chklen = sizeof(struct rte) + sizeof(rr_t);
867                                 if (! (t = pkg_malloc(chklen))) {
868                                         ERR("out of pkg memory (%d required)\n", (int)chklen);
869                                         goto end;
870                                 }
871                                 /* this way, .free_rr is also set to 0 (!!!) */
872                                 memset(t, 0, chklen); 
873                                 ((rr_t *)&t[1])->nameaddr.name = *contact;
874                                 ((rr_t *)&t[1])->len = contact->len;
875                                 /* chain the new route elem in set */
876                                 if (prev_t == rtset)
877                                         /*there is only one elem in route set: the remote target*/
878                                         rtset = t;
879                                 else
880                                         prev_t->next = t;
881                         }
882
883                         *ruri = *GET_RURI(&orig_inv); /* reuse original RURI */
884                         *next_hop = *ruri;
885                         break;
886                 default:
887                         /* probably a mem corruption */
888                         BUG("next hop of original request marked as both loose and strict"
889                                         " router (buffer: %.*s).\n", inv_rb->buffer_len, 
890                                         inv_rb->buffer);
891 #ifdef EXTRA_DEBUG
892                         abort();
893 #else
894                         goto end;
895 #endif
896                 }
897         }
898
899         *list = rtset;
900         /* all went well */
901         ret = 0;
902 end:
903         free_sip_msg(&orig_inv);
904         if (ret < 0)
905                 free_rte_list(rtset);
906         return ret;
907 }
908
909      /*
910       * The function creates an ACK to 200 OK. Route set will be created
911       * and parsed and the dst parameter will contain the destination to which 
912           * the request should be send. The function is used by tm when it 
913           * generates local ACK to 200 OK (on behalf of applications using uac)
914       */
915 char *build_dlg_ack(struct sip_msg* rpl, struct cell *Trans, 
916                                         unsigned int branch, str *hdrs, str *body,
917                                         unsigned int *len, struct dest_info* dst)
918 {
919         char *req_buf, *p, *via;
920         unsigned int via_len;
921         char branch_buf[MAX_BRANCH_PARAM_LEN];
922         int branch_len;
923         str branch_str;
924         struct hostport hp;
925         struct rte* list;
926         str contact, ruri, *cont;
927         str next_hop;
928         str body_len;
929         str _to, *to = &_to;
930 #ifdef USE_DNS_FAILOVER
931         struct dns_srv_handle dns_h;
932 #endif
933 #ifdef WITH_AS_SUPPORT
934         /* With AS support, TM allows for external modules to generate building of
935          * the ACK; in this case, the ACK's retransmission buffer is built once
936          * and kept in memory (to help when retransmitted 2xx are received and ACK
937          * must be resent).
938          * Allocation of the string raw buffer that holds the ACK is piggy-backed
939          * with allocation of the retransmission buffer (since both have the same
940          * life-cycle): both the string buffer and retransm. buffer are placed 
941          * into the same allocated chunk of memory (retr. buffer first, string 
942          * buffer follows).In this case, the 'len' param is used as in-out 
943          * parameter: 'in' to give the extra space needed by the retr. buffer,
944          * 'out' to return the lenght of the allocated string buffer.
945          */
946         unsigned offset = *len;
947 #endif
948         
949         if (parse_headers(rpl, HDR_EOH_F, 0) == -1 || !rpl->to) {
950                 ERR("Error while parsing headers.\n");
951                 return 0;
952         } else {
953                 _to.s = rpl->to->name.s;
954                 _to.len = rpl->to->len;
955         }
956         
957         if (get_contact_uri(rpl, &contact) < 0) {
958                 return 0;
959         }
960         
961         if (eval_uac_routing(rpl, &Trans->uac[branch].request, &contact, 
962                         &list, &ruri, &next_hop) < 0) {
963                 ERR("failed to evaluate routing elements.\n");
964                 return 0;
965         }
966         DEBUG("ACK RURI: `%.*s', NH: `%.*s'.\n", STR_FMT(&ruri), 
967                         STR_FMT(&next_hop));
968
969         if ((contact.s != ruri.s) || (contact.len != ruri.len)) {
970                      /* contact != ruri means that the next
971                       * hop is a strict router, cont will be non-zero
972                       * and print_routeset will append it at the end
973                       * of the route set
974                       */
975                 cont = &contact;
976         } else {
977                      /* Next hop is a loose router, nothing to append */
978                 cont = 0;
979         }
980         
981              /* method, separators, version: "ACK sip:p2@iptel.org SIP/2.0" */
982         *len = SIP_VERSION_LEN + ACK_LEN + 2 /* spaces */ + CRLF_LEN;
983         *len += ruri.len;
984         
985         /* dst */
986         switch(cfg_get(tm, tm_cfg, local_ack_mode)){
987                 case 1:
988                         /* send the local 200 ack to the same dst as the corresp. invite*/
989                         *dst=Trans->uac[branch].request.dst;
990                         break;
991                 case 2: 
992                         /* send the local 200 ack to the same dst as the 200 reply source*/
993                         init_dst_from_rcv(dst, &rpl->rcv);
994                         dst->send_flags=rpl->fwd_send_flags;
995                         break;
996                 case 0:
997                 default:
998                         /* rfc conformant behaviour: use the next_hop determined from the
999                            contact and the route set */
1000 #ifdef USE_DNS_FAILOVER
1001                 if (cfg_get(core, core_cfg, use_dns_failover)){
1002                         dns_srv_handle_init(&dns_h);
1003                         if ((uri2dst(&dns_h , dst, rpl, &next_hop, PROTO_NONE)==0) ||
1004                                         (dst->send_sock==0)){
1005                                 dns_srv_handle_put(&dns_h);
1006                                 LOG(L_ERR, "build_dlg_ack: no socket found\n");
1007                                 goto error;
1008                         }
1009                         dns_srv_handle_put(&dns_h); /* not needed any more */
1010                 }else{
1011                         if ((uri2dst(0 , dst, rpl, &next_hop, PROTO_NONE)==0) ||
1012                                         (dst->send_sock==0)){
1013                                 LOG(L_ERR, "build_dlg_ack: no socket found\n");
1014                                 goto error;
1015                         }
1016                 }
1017 #else /* USE_DNS_FAILOVER */
1018                 if ( (uri2dst( dst, rpl, &next_hop, PROTO_NONE)==0) ||
1019                                 (dst->send_sock==0)){
1020                                 LOG(L_ERR, "build_dlg_ack: no socket found\n");
1021                         goto error;
1022                 }
1023 #endif /* USE_DNS_FAILOVER */
1024                 break;
1025         }
1026         
1027          /* via */
1028         if (!t_calc_branch(Trans,  branch, branch_buf, &branch_len)) goto error;
1029         branch_str.s = branch_buf;
1030         branch_str.len = branch_len;
1031         set_hostport(&hp, 0);
1032         via = via_builder(&via_len, dst, &branch_str, 0, &hp);
1033         if (!via) {
1034                 LOG(L_ERR, "build_dlg_ack: No via header got from builder\n");
1035                 goto error;
1036         }
1037         *len+= via_len;
1038         
1039              /*headers*/
1040         *len += Trans->from.len + Trans->callid.len + to->len + Trans->cseq_n.len + 1 + ACK_LEN + CRLF_LEN;
1041         
1042              /* copy'n'paste Route headers */
1043         
1044         *len += calc_routeset_len(list, cont);
1045         
1046              /* User Agent */
1047         if (server_signature) *len += user_agent_hdr.len + CRLF_LEN;
1048                 /* extra headers */
1049         if (hdrs)
1050                 *len += hdrs->len;
1051                 /* body */
1052         if (body) {
1053                 body_len.s = int2str(body->len, &body_len.len);
1054                 *len += body->len;
1055         } else {
1056                 body_len.len = 0;
1057                 body_len.s = NULL; /*4gcc*/
1058                 *len += 1; /* for the (Cont-Len:) `0' */
1059         }
1060              /* Content Length, EoM */
1061         *len += CONTENT_LENGTH_LEN + body_len.len + CRLF_LEN + CRLF_LEN;
1062
1063 #if WITH_AS_SUPPORT
1064         req_buf = shm_malloc(offset + *len + 1);
1065         req_buf += offset;
1066 #else
1067         req_buf = shm_malloc(*len + 1);
1068 #endif
1069         if (!req_buf) {
1070                 ERR("Cannot allocate memory (%u+1)\n", *len);
1071                 goto error01;
1072         }
1073         p = req_buf;
1074         
1075         append_str( p, ACK, ACK_LEN );
1076         append_str( p, " ", 1 );
1077         append_str(p, ruri.s, ruri.len);
1078         append_str( p, " " SIP_VERSION CRLF, 1 + SIP_VERSION_LEN + CRLF_LEN);
1079          
1080              /* insert our via */
1081         append_str(p, via, via_len);
1082         
1083              /*other headers*/
1084         append_str(p, Trans->from.s, Trans->from.len);
1085         append_str(p, Trans->callid.s, Trans->callid.len);
1086         append_str(p, to->s, to->len);
1087         
1088         append_str(p, Trans->cseq_n.s, Trans->cseq_n.len);
1089         append_str( p, " ", 1 );
1090         append_str( p, ACK, ACK_LEN);
1091         append_str(p, CRLF, CRLF_LEN);
1092         
1093              /* Routeset */
1094         p = print_rs(p, list, cont);
1095         
1096              /* User Agent header */
1097         if (server_signature) {
1098                 append_str(p, user_agent_hdr.s, user_agent_hdr.len);
1099                 append_str(p, CRLF, CRLF_LEN);
1100         }
1101         
1102         /* extra headers */
1103         if (hdrs)
1104                 append_str(p, hdrs->s, hdrs->len);
1105         
1106              /* Content Length, EoH, (body) */
1107         if (body) {
1108                 append_str(p, CONTENT_LENGTH, CONTENT_LENGTH_LEN);
1109                 append_str(p, body_len.s, body_len.len);
1110                 append_str(p, /*end crr. header*/CRLF /*EoH*/CRLF, CRLF_LEN + 
1111                                 CRLF_LEN);
1112                 append_str(p, body->s, body->len);
1113         } else {
1114                 append_str(p, CONTENT_LENGTH "0" CRLF CRLF, 
1115                                 CONTENT_LENGTH_LEN + 1 + CRLF_LEN + CRLF_LEN);
1116         }
1117
1118         /* EoM */
1119         *p = 0;
1120         
1121         pkg_free(via);
1122         free_rte_list(list);
1123         return req_buf;
1124         
1125  error01:
1126         pkg_free(via);
1127  error:
1128         free_rte_list(list);
1129         return 0;
1130 }
1131
1132
1133 /*
1134  * Convert length of body into asciiz
1135  */
1136 static inline int print_content_length(str* dest, str* body)
1137 {
1138         static char content_length[10];
1139         int len;
1140         int b_len;
1141         char* tmp;
1142
1143              /* Print Content-Length */
1144         b_len=body?body->len:0;
1145         tmp = int2str(b_len, &len);
1146         if (len >= sizeof(content_length)) {
1147                 LOG(L_ERR, "ERROR: print_content_length: content_len too big\n");
1148                 dest->s = 0;
1149                 dest->len = 0;
1150                 return -1;
1151         }
1152         memcpy(content_length, tmp, len); 
1153         dest->s = content_length;
1154         dest->len = len;
1155         return 0;
1156 }
1157
1158
1159 /*
1160  * Convert CSeq number into asciiz
1161  */
1162 static inline int print_cseq_num(str* _s, dlg_t* _d)
1163 {
1164         static char cseq[INT2STR_MAX_LEN];
1165         char* tmp;
1166         int len;
1167
1168         tmp = int2str(_d->loc_seq.value, &len);
1169         if (len > sizeof(cseq)) {
1170                 LOG(L_ERR, "print_cseq_num: cseq too big\n");
1171                 return -1;
1172         }
1173         
1174         memcpy(cseq, tmp, len);
1175         _s->s = cseq;
1176         _s->len = len;
1177         return 0;
1178 }
1179
1180
1181 /*
1182  * Create Via header
1183  */
1184 static inline int assemble_via(str* dest, struct cell* t, 
1185                                                                 struct dest_info* dst, int branch)
1186 {
1187         static char branch_buf[MAX_BRANCH_PARAM_LEN];
1188         char* via;
1189         int len;
1190         unsigned int via_len;
1191         str branch_str;
1192         struct hostport hp;
1193
1194         if (!t_calc_branch(t, branch, branch_buf, &len)) {
1195                 LOG(L_ERR, "ERROR: assemble_via: branch calculation failed\n");
1196                 return -1;
1197         }
1198         
1199         branch_str.s = branch_buf;
1200         branch_str.len = len;
1201
1202 #ifdef XL_DEBUG
1203         printf("!!!proto: %d\n", sock->proto);
1204 #endif
1205
1206         set_hostport(&hp, 0);
1207         via = via_builder(&via_len, dst, &branch_str, 0, &hp);
1208         if (!via) {
1209                 LOG(L_ERR, "assemble_via: via building failed\n");
1210                 return -2;
1211         }
1212         
1213         dest->s = via;
1214         dest->len = via_len;
1215         return 0;
1216 }
1217
1218
1219 /*
1220  * Print Request-URI
1221  */
1222 static inline char* print_request_uri(char* w, str* method, dlg_t* dialog, struct cell* t, int branch)
1223 {
1224         memapp(w, method->s, method->len); 
1225         memapp(w, " ", 1); 
1226
1227         t->uac[branch].uri.s = w; 
1228         t->uac[branch].uri.len = dialog->hooks.request_uri->len;
1229
1230         memapp(w, dialog->hooks.request_uri->s, dialog->hooks.request_uri->len); 
1231         memapp(w, " " SIP_VERSION CRLF, 1 + SIP_VERSION_LEN + CRLF_LEN);
1232
1233         return w;
1234 }
1235
1236
1237 /*
1238  * Print To header field
1239  */
1240 static inline char* print_to(char* w, dlg_t* dialog, struct cell* t)
1241 {
1242         t->to.s = w;
1243         t->to.len = TO_LEN + dialog->rem_uri.len + CRLF_LEN;
1244
1245         memapp(w, TO, TO_LEN);
1246         memapp(w, dialog->rem_uri.s, dialog->rem_uri.len);
1247
1248         if (dialog->id.rem_tag.len) {
1249                 t->to.len += TOTAG_LEN + dialog->id.rem_tag.len ;
1250                 memapp(w, TOTAG, TOTAG_LEN);
1251                 memapp(w, dialog->id.rem_tag.s, dialog->id.rem_tag.len);
1252         }
1253
1254         memapp(w, CRLF, CRLF_LEN);
1255         return w;
1256 }
1257
1258
1259 /*
1260  * Print From header field
1261  */
1262 static inline char* print_from(char* w, dlg_t* dialog, struct cell* t)
1263 {
1264         t->from.s = w;
1265         t->from.len = FROM_LEN + dialog->loc_uri.len + CRLF_LEN;
1266
1267         memapp(w, FROM, FROM_LEN);
1268         memapp(w, dialog->loc_uri.s, dialog->loc_uri.len);
1269
1270         if (dialog->id.loc_tag.len) {
1271                 t->from.len += FROMTAG_LEN + dialog->id.loc_tag.len;
1272                 memapp(w, FROMTAG, FROMTAG_LEN);
1273                 memapp(w, dialog->id.loc_tag.s, dialog->id.loc_tag.len);
1274         }
1275
1276         memapp(w, CRLF, CRLF_LEN);
1277         return w;
1278 }
1279
1280
1281 /*
1282  * Print CSeq header field
1283  */
1284 char* print_cseq_mini(char* target, str* cseq, str* method) {
1285         memapp(target, CSEQ, CSEQ_LEN);
1286         memapp(target, cseq->s, cseq->len);
1287         memapp(target, " ", 1);
1288         memapp(target, method->s, method->len);
1289         return target;
1290 }
1291
1292 static inline char* print_cseq(char* w, str* cseq, str* method, struct cell* t)
1293 {
1294         t->cseq_n.s = w; 
1295         /* don't include method name and CRLF -- subsequent
1296          * local requests ACK/CANCEL will add their own */
1297         t->cseq_n.len = CSEQ_LEN + cseq->len; 
1298         w = print_cseq_mini(w, cseq, method);
1299         return w;
1300 }
1301
1302 /*
1303  * Print Call-ID header field
1304  * created an extra function for pure header field creation, that is used by t_cancel for 
1305  * t_uac_cancel FIFO function.
1306  */
1307 char* print_callid_mini(char* target, str callid) {
1308         memapp(target, CALLID, CALLID_LEN);
1309         memapp(target, callid.s, callid.len);
1310         memapp(target, CRLF, CRLF_LEN);
1311         return target;
1312 }
1313
1314 static inline char* print_callid(char* w, dlg_t* dialog, struct cell* t)
1315 {
1316         /* begins with CRLF, not included in t->callid, don`t know why...?!? */
1317         memapp(w, CRLF, CRLF_LEN);
1318         t->callid.s = w;
1319         t->callid.len = CALLID_LEN + dialog->id.call_id.len + CRLF_LEN;
1320
1321         w = print_callid_mini(w, dialog->id.call_id);
1322         return w;
1323 }
1324
1325
1326 /*
1327  * Create a request
1328  */
1329 char* build_uac_req(str* method, str* headers, str* body, dlg_t* dialog, int branch, 
1330                         struct cell *t, int* len, struct dest_info* dst)
1331 {
1332         char* buf, *w;
1333         str content_length, cseq, via;
1334
1335         if (!method || !dialog) {
1336                 LOG(L_ERR, "build_uac_req(): Invalid parameter value\n");
1337                 return 0;
1338         }
1339         if (print_content_length(&content_length, body) < 0) {
1340                 LOG(L_ERR, "build_uac_req(): Error while printing content-length\n");
1341                 return 0;
1342         }
1343         if (print_cseq_num(&cseq, dialog) < 0) {
1344                 LOG(L_ERR, "build_uac_req(): Error while printing CSeq number\n");
1345                 return 0;
1346         }
1347         *len = method->len + 1 + dialog->hooks.request_uri->len + 1 + SIP_VERSION_LEN + CRLF_LEN;
1348
1349         if (assemble_via(&via, t, dst, branch) < 0) {
1350                 LOG(L_ERR, "build_uac_req(): Error while assembling Via\n");
1351                 return 0;
1352         }
1353         *len += via.len;
1354
1355         *len += TO_LEN + dialog->rem_uri.len
1356                 + (dialog->id.rem_tag.len ? (TOTAG_LEN + dialog->id.rem_tag.len) : 0) + CRLF_LEN;    /* To */
1357         *len += FROM_LEN + dialog->loc_uri.len
1358                 + (dialog->id.loc_tag.len ? (FROMTAG_LEN + dialog->id.loc_tag.len) : 0) + CRLF_LEN;  /* From */
1359         *len += CALLID_LEN + dialog->id.call_id.len + CRLF_LEN;                                      /* Call-ID */
1360         *len += CSEQ_LEN + cseq.len + 1 + method->len + CRLF_LEN;                                    /* CSeq */
1361         *len += calculate_routeset_length(dialog);                                                   /* Route set */
1362         *len += CONTENT_LENGTH_LEN + content_length.len + CRLF_LEN; /* Content-
1363                                                                                                                                          Length */
1364         *len += (server_signature ? (user_agent_hdr.len + CRLF_LEN) : 0);                                /* Signature */
1365         *len += (headers ? headers->len : 0);                                                        /* Additional headers */
1366         *len += (body ? body->len : 0);                                                              /* Message body */
1367         *len += CRLF_LEN;                                                                            /* End of Header */
1368
1369         buf = shm_malloc(*len + 1);
1370         if (!buf) {
1371                 LOG(L_ERR, "build_uac_req(): no shmem\n");
1372                 goto error;
1373         }
1374         
1375         w = buf;
1376
1377         w = print_request_uri(w, method, dialog, t, branch);  /* Request-URI */
1378         memapp(w, via.s, via.len);                            /* Top-most Via */
1379         w = print_to(w, dialog, t);                           /* To */
1380         w = print_from(w, dialog, t);                         /* From */
1381         w = print_cseq(w, &cseq, method, t);                  /* CSeq */
1382         w = print_callid(w, dialog, t);                       /* Call-ID */
1383         w = print_routeset(w, dialog);                        /* Route set */
1384
1385      /* Content-Length */
1386         memapp(w, CONTENT_LENGTH, CONTENT_LENGTH_LEN);
1387         memapp(w, content_length.s, content_length.len);
1388         memapp(w, CRLF, CRLF_LEN);
1389         
1390              /* Server signature */
1391         if (server_signature) {
1392                 memapp(w, user_agent_hdr.s, user_agent_hdr.len);
1393                 memapp(w, CRLF, CRLF_LEN);
1394         }
1395         if (headers) memapp(w, headers->s, headers->len);
1396         memapp(w, CRLF, CRLF_LEN);
1397         if (body) memapp(w, body->s, body->len);
1398
1399 #ifdef EXTRA_DEBUG
1400         assert(w-buf == *len);
1401 #endif
1402
1403         pkg_free(via.s);
1404         return buf;
1405
1406  error:
1407         pkg_free(via.s);
1408         return 0;
1409 }
1410
1411
1412 int t_calc_branch(struct cell *t, 
1413         int b, char *branch, int *branch_len)
1414 {
1415         return syn_branch ?
1416                 branch_builder( t->hash_index,
1417                         t->label, 0,
1418                         b, branch, branch_len )
1419                 : branch_builder( t->hash_index,
1420                         0, t->md5,
1421                         b, branch, branch_len );
1422 }
1423