Merge remote branch 'origin/sr_3.0'
[sip-router] / msg_translator.c
1 /*
2  * $Id$
3  *
4  *
5  * Copyright (C) 2001-2003 FhG Fokus
6  *
7  * This file is part of ser, a free SIP server.
8  *
9  * ser is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version
13  *
14  * For a license to use the ser software under conditions
15  * other than those described here, or to purchase support for this
16  * software, please contact iptel.org by e-mail at the following addresses:
17  *    info@iptel.org
18  *
19  * ser is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
27  *
28  *
29  * History:
30  * --------
31  * 2003-01-20  bug_fix: use of return value of snprintf aligned to C99 (jiri)
32  * 2003-01-23  added rport patches, contributed by
33  *              Maxim Sobolev <sobomax@FreeBSD.org> and heavily modified by me
34  *              (andrei)
35  * 2003-01-24  added i param to via of outgoing requests (used by tcp),
36  *              modified via_builder params (andrei)
37  * 2003-01-27  more rport fixes (make use of new via_param->start)  (andrei)
38  * 2003-01-27  next baby-step to removing ZT - PRESERVE_ZT (jiri)
39  * 2003-01-29  scratchpad removed (jiri)
40  * 2003-02-28  scratchpad compatibility abandoned (jiri)
41  * 2003-03-01  VOICE_MAIL defs removed (jiri)
42  * 2003-03-06  totags in outgoing replies bookmarked to enable
43  *             ACK/200 tag matching (andrei)
44  * 2003-03-18  killed the build_warning snprintf (andrei)
45  * 2003-03-31  added subst lump support (andrei)
46  * 2003-04-01  added opt (conditional) lump support (andrei)
47  * 2003-04-02  added more subst lumps: SUBST_{SND,RCV}_ALL
48  *              => ip:port;transport=proto (andrei)
49  * 2003-04-12  added FL_FORCE_RPORT support (andrei)
50  * 2003-04-13  updated warning builder -- fixed (andrei)
51  * 2003-07-10  check_via_address knows now how to compare with ipv6 address
52  *              references (e.g [::1]) (andrei)
53  *             build_req_fomr_sip_req no longer adds 1 for ipv6 via parameter
54  *              position calculations ([] are part of host.s now) (andrei)
55  * 2003-10-02  via+lump dst address/port can be set to preset values (andrei)
56  * 2003-10-08  receive_test function-alized (jiri)
57  * 2003-10-20  added body_lump list (sip_msg), adjust_clen (andrei & jan)
58  * 2003-11-11  type of rpl_lumps replaced by flags (bogdan)
59  * 2006-04-20  build_req_from_sip_req, via_builder and lump_* functions
60  *              use now struct dest_info; lumps & via comp param support
61  *              (rfc3486) (andrei)
62  * 2007-08-31  id_builder() and via_builder() are grouped into one function:
63  *             create_via_hf() -- tm module needs them as well (Miklos)
64  * 2008-12-17  build_req_from_sip_req() will now fallback to tcp, tls or sctp
65  *              if packet size > udp_mtu and fallback is enabled 
66  *             build_req_from_sip_req() uses now global_req_flags along
67  *               msg->msg_flags  (andrei)
68  *
69  */
70 /* Via special params:
71  * requests:
72  * - if the address in via is different from the src_ip or an existing
73  *   received=something is found, received=src_ip is added (and any preexisting
74  *   received is deleted). received is added as the first via parameter if no
75  *   receive is previously present or over the old receive.
76  * - if the original via contains rport / rport=something or msg->msg_flags
77  *   FL_FORCE_RPORT is set (e.g. script force_rport() cmd) rport=src_port
78  *   is added (over previous rport / as first via param or after received
79  *   if no received was present and received is added too)
80  * local replies:
81  *    (see also sl_send_reply)
82  *  - rport and received are added in mostly the same way as for requests, but
83  *    in the reverse order (first rport and then received). See also
84  *    limitations.
85  *  - if reply_to_via is set (default off) the local reply will be sent to
86  *    the address in via (received is ignored since it was not set by us). The
87  *    destination port is either the message source port if via contains rport
88  *    or the FL_FORCE_RPORT flag is set or the port from the via. If either
89  *    port or rport are present a normal dns lookup (instead of a srv lookup)
90  *    is performed on the address. If no port is present and a srv lookup is
91  *    performed the port is taken from the srv lookup. If the srv lookup failed
92  *    or it was not performed, the port is set to the default sip port (5060).
93  *  - if reply_to_via is off (default) the local reply is sent to the message
94  *    source ip address. The destination port is set to the source port if
95  *    rport is present or FL_FORCE_RPORT flag is set, to the via port or to
96  *    the default sip port (5060) if neither rport or via port are present.
97  * "normal" replies:
98  *  - if received is present the message is sent to the received address else
99  *    if no port is present (neither a normal via port or rport) a dns srv
100  *    lookup is performed on the host part and the reply is sent to the
101  *    resulting ip. If a port is present or the host part is an ip address
102  *    the dns lookup will be a "normal" one (A or AAAA).
103  *  - if rport is present, it's value will be used as the destination port
104  *   (and this will also disable srv lookups)
105  *  - if no port is present the destination port will be taken from the srv
106  *    lookup. If the srv lookup fails or is not performed (e.g. ip address
107  *    in host) the destination port will be set to the default sip port (5060).
108  *
109  * Known limitations:
110  * - when locally replying to a message, rport and received will be appended to
111  *   the via header parameters (for forwarded requests they are inserted at the
112  *   beginning).
113  * - a locally generated reply might get two received via parameters if a
114  *   received is already present in the original message (this should not
115  *   happen though, but ...)
116  *
117  *--andrei
118 */
119
120 /*!
121  * \file
122  * \brief SIP-router core :: 
123  * \ingroup core
124  * Module: \ref core
125  */
126
127 #include <sys/types.h>
128 #include <sys/socket.h>
129 #include <netdb.h>
130 #include <string.h>
131 #include <stdio.h>
132 #include <stdlib.h>
133
134 #include "comp_defs.h"
135 #include "msg_translator.h"
136 #include "globals.h"
137 #include "error.h"
138 #include "mem/mem.h"
139 #include "dprint.h"
140 #include "config.h"
141 #include "md5utils.h"
142 #include "data_lump.h"
143 #include "data_lump_rpl.h"
144 #include "ip_addr.h"
145 #include "resolve.h"
146 #include "ut.h"
147 #include "pt.h"
148 #include "cfg/cfg.h"
149 #include "parser/parse_to.h"
150 #include "forward.h"
151
152
153 #define append_str_trans(_dest,_src,_len,_msg) \
154         append_str( (_dest), (_src), (_len) );
155
156 extern char version[];
157 extern int version_len;
158
159 /* global flags for build_req_from_sip_req */
160 static unsigned int global_req_flags=0;
161
162
163
164 /** per process fixup function for global_req_flags.
165   * It should be called from the configuration framework.
166   */
167 void fix_global_req_flags(str* gname, str* name)
168 {
169         global_req_flags=0;
170         switch(cfg_get(core, core_cfg, udp_mtu_try_proto)){
171                 case PROTO_NONE:
172                 case PROTO_UDP:
173                         /* do nothing */
174                         break;
175                 case PROTO_TCP:
176                         global_req_flags|=FL_MTU_TCP_FB;
177                         break;
178                 case PROTO_TLS:
179                         global_req_flags|=FL_MTU_TLS_FB;
180                         break;
181                 case PROTO_SCTP:
182                         global_req_flags|=FL_MTU_SCTP_FB;
183                         break;
184         }
185         if (cfg_get(core, core_cfg, force_rport))
186                 global_req_flags|=FL_FORCE_RPORT;
187 }
188
189
190
191 /* checks if ip is in host(name) and ?host(ip)=name?
192  * ip must be in network byte order!
193  *  resolver = DO_DNS | DO_REV_DNS; if 0 no dns check is made
194  * return 0 if equal */
195 static int check_via_address(struct ip_addr* ip, str *name,
196                                 unsigned short port, int resolver)
197 {
198         struct hostent* he;
199         int i;
200         char* s;
201         int len;
202
203         /* maybe we are lucky and name it's an ip */
204         s=ip_addr2a(ip);
205         if (s){
206                 DBG("check_via_address(%s, %.*s, %d)\n",
207                         s, name->len, name->s, resolver);
208                 len=strlen(s);
209
210         #ifdef USE_IPV6
211                 /* check if name->s is an ipv6 address or an ipv6 address ref. */
212                 if ((ip->af==AF_INET6) &&
213                                 (       ((len==name->len)&&(strncasecmp(name->s, s, name->len)==0))
214                                         ||
215                                         ((len==(name->len-2))&&(name->s[0]=='[')&&
216                                                 (name->s[name->len-1]==']')&&
217                                                 (strncasecmp(name->s+1, s, len)==0))
218                                 )
219                    )
220                         return 0;
221                 else
222         #endif
223
224                         if (strncmp(name->s, s, name->len)==0)
225                                 return 0;
226         }else{
227                 LOG(L_CRIT, "check_via_address: BUG: could not convert ip address\n");
228                 return -1;
229         }
230
231         if (port==0) port=SIP_PORT;
232         if (resolver&DO_DNS){
233                 DBG("check_via_address: doing dns lookup\n");
234                 /* try all names ips */
235                 he=sip_resolvehost(name, &port, 0); /* don't use naptr */
236                 if (he && ip->af==he->h_addrtype){
237                         for(i=0;he && he->h_addr_list[i];i++){
238                                 if ( memcmp(&he->h_addr_list[i], ip->u.addr, ip->len)==0)
239                                         return 0;
240                         }
241                 }
242         }
243         if (resolver&DO_REV_DNS){
244                 DBG("check_via_address: doing rev. dns lookup\n");
245                 /* try reverse dns */
246                 he=rev_resolvehost(ip);
247                 if (he && (strncmp(he->h_name, name->s, name->len)==0))
248                         return 0;
249                 for (i=0; he && he->h_aliases[i];i++){
250                         if (strncmp(he->h_aliases[i],name->s, name->len)==0)
251                                 return 0;
252                 }
253         }
254         return -1;
255 }
256
257
258 /* check if IP address in Via != source IP address of signaling */
259 int received_test( struct sip_msg *msg )
260 {
261         int rcvd;
262
263         rcvd=msg->via1->received
264                         || check_via_address(&msg->rcv.src_ip, &msg->via1->host,
265                                                         msg->via1->port, received_dns);
266         return rcvd;
267 }
268
269
270 static char * warning_builder( struct sip_msg *msg, unsigned int *returned_len)
271 {
272         static char buf[MAX_WARNING_LEN];
273         str *foo;
274         int print_len, l;
275         int clen;
276         char* t;
277
278 #define str_print(string, string_len) \
279                 do{ \
280                         l=(string_len); \
281                         if ((clen+l)>MAX_WARNING_LEN) \
282                                 goto error_overflow; \
283                         memcpy(buf+clen, (string), l); \
284                         clen+=l; \
285                 }while(0)
286
287 #define str_lenpair_print(string, string_len, string2, string2_len) \
288                 do{ \
289                         str_print(string, string_len); \
290                         str_print(string2, string2_len);\
291                 }while(0)
292
293 #define str_pair_print( string, string2, string2_len) \
294                 str_lenpair_print((string), strlen((string)), (string2), (string2_len))
295
296 #define str_int_print(string, intval)\
297                 do{\
298                         t=int2str((intval), &print_len); \
299                         str_pair_print(string, t, print_len);\
300                 } while(0)
301
302 #define str_su_print(sockaddr)\
303                 do{\
304                         t=su2a(&sockaddr, sizeof(sockaddr)); \
305                         print_len=strlen(t); \
306                         str_print(t, print_len); \
307                 } while(0)
308
309 #define str_ipaddr_print(string, ipaddr_val)\
310                 do{\
311                         t=ip_addr2a((ipaddr_val)); \
312                         print_len=strlen(t); \
313                         str_pair_print(string, t, print_len);\
314                 } while(0)
315
316         clen=0;
317         str_print(WARNING, WARNING_LEN);
318         str_su_print(msg->rcv.bind_address->su);
319         str_print(WARNING_PHRASE, WARNING_PHRASE_LEN);
320
321         /*adding out_uri*/
322         if (msg->new_uri.s)
323                 foo=&(msg->new_uri);
324         else
325                 foo=&(msg->first_line.u.request.uri);
326         /* pid= */
327         str_int_print(" pid=", my_pid());
328         /* req_src_ip= */
329         str_ipaddr_print(" req_src_ip=", &msg->rcv.src_ip);
330         str_int_print(" req_src_port=", msg->rcv.src_port);
331         str_pair_print(" in_uri=", msg->first_line.u.request.uri.s,
332                                                                 msg->first_line.u.request.uri.len);
333         str_pair_print(" out_uri=", foo->s, foo->len);
334         str_pair_print(" via_cnt",
335                                         (msg->parsed_flag & HDR_EOH_F)==HDR_EOH_F ? "=" : ">", 1);
336         str_int_print("=", via_cnt);
337         if (clen<MAX_WARNING_LEN){ buf[clen]='"'; clen++; }
338         else goto error_overflow;
339
340
341         *returned_len=clen;
342         return buf;
343 error_overflow:
344         LOG(L_NOTICE, "NOTICE: warning_builder: buffer size exceeded (probably too long URI)\n");
345         *returned_len=0;
346         return 0;
347 }
348
349
350
351
352 char* received_builder(struct sip_msg *msg, unsigned int *received_len)
353 {
354         char *buf;
355         int  len;
356         struct ip_addr *source_ip;
357         char *tmp;
358         int  tmp_len;
359
360         source_ip=&msg->rcv.src_ip;
361
362         buf=pkg_malloc(sizeof(char)*MAX_RECEIVED_SIZE);
363         if (buf==0){
364                 ser_error=E_OUT_OF_MEM;
365                 LOG(L_ERR, "ERROR: received_builder: out of memory\n");
366                 return 0;
367         }
368         memcpy(buf, RECEIVED, RECEIVED_LEN);
369         if ( (tmp=ip_addr2a(source_ip))==0)
370                 return 0; /* error*/
371         tmp_len=strlen(tmp);
372         len=RECEIVED_LEN+tmp_len;
373
374         memcpy(buf+RECEIVED_LEN, tmp, tmp_len);
375         buf[len]=0; /*null terminate it */
376
377         *received_len = len;
378         return buf;
379 }
380
381
382
383 char* rport_builder(struct sip_msg *msg, unsigned int *rport_len)
384 {
385         char* buf;
386         char* tmp;
387         int tmp_len;
388         int len;
389
390         tmp_len=0;
391         tmp=int2str(msg->rcv.src_port, &tmp_len);
392         len=RPORT_LEN+tmp_len;
393         buf=pkg_malloc(sizeof(char)*(len+1));/* space for null term */
394         if (buf==0){
395                 ser_error=E_OUT_OF_MEM;
396                 LOG(L_ERR, "ERROR: rport_builder: out of memory\n");
397                 return 0;
398         }
399         memcpy(buf, RPORT, RPORT_LEN);
400         memcpy(buf+RPORT_LEN, tmp, tmp_len);
401         buf[len]=0; /*null terminate it*/
402
403         *rport_len=len;
404         return buf;
405 }
406
407
408
409 char* id_builder(struct sip_msg* msg, unsigned int *id_len)
410 {
411         char* buf;
412         int len, value_len;
413         char revhex[sizeof(int)*2];
414         char* p;
415         int size;
416
417         size=sizeof(int)*2;
418         p=&revhex[0];
419         if (int2reverse_hex(&p, &size, msg->rcv.proto_reserved1)==-1){
420                 LOG(L_CRIT, "BUG: id_builder: not enough space for id\n");
421                 return 0;
422         }
423         value_len=p-&revhex[0];
424         len=ID_PARAM_LEN+value_len;
425         buf=pkg_malloc(sizeof(char)*(len+1));/* place for ending \0 */
426         if (buf==0){
427                 ser_error=E_OUT_OF_MEM;
428                 LOG(L_ERR, "ERROR: id_builder: out of memory\n");
429                 return 0;
430         }
431         memcpy(buf, ID_PARAM, ID_PARAM_LEN);
432         memcpy(buf+ID_PARAM_LEN, revhex, value_len);
433         buf[len]=0; /* null terminate it */
434         *id_len=len;
435         return buf;
436 }
437
438
439
440 char* clen_builder(     struct sip_msg* msg, int *clen_len, int diff, 
441                                         int body_only)
442 {
443         char* buf;
444         int len;
445         int value;
446         char* value_s;
447         int value_len;
448         char* body;
449
450
451         body=get_body(msg);
452         if (body==0){
453                 ser_error=E_BAD_REQ;
454                 LOG(L_ERR, "ERROR: clen_builder: no message body found"
455                                         " (missing crlf?)");
456                 return 0;
457         }
458         value=msg->len-(int)(body-msg->buf)+diff;
459         value_s=int2str(value, &value_len);
460         DBG("clen_builder: content-length: %d (%s)\n", value, value_s);
461
462         if (body_only) {
463                 len=value_len;
464         }
465         else {
466                 len=CONTENT_LENGTH_LEN+value_len+CRLF_LEN;
467         }
468         buf=pkg_malloc(sizeof(char)*(len+1));
469         if (buf==0){
470                 ser_error=E_OUT_OF_MEM;
471                 LOG(L_ERR, "ERROR: clen_builder: out of memory\n");
472                 return 0;
473         }
474         if (body_only) {
475                 memcpy(buf, value_s, value_len);
476         }
477         else {
478                 memcpy(buf, CONTENT_LENGTH, CONTENT_LENGTH_LEN);
479                 memcpy(buf+CONTENT_LENGTH_LEN, value_s, value_len);
480                 memcpy(buf+CONTENT_LENGTH_LEN+value_len, CRLF, CRLF_LEN);
481         }
482         buf[len]=0; /* null terminate it */
483         *clen_len=len;
484         return buf;
485 }
486
487
488
489 /* checks if a lump opt condition
490  * returns 1 if cond is true, 0 if false */
491 static inline int lump_check_opt(       struct lump *l,
492                                                                         struct sip_msg* msg,
493                                                                         struct dest_info* snd_i
494                                                                         )
495 {
496         struct ip_addr* ip;
497         unsigned short port;
498         int proto;
499
500 #define get_ip_port_proto \
501                         if ((snd_i==0) || (snd_i->send_sock==0)){ \
502                                 LOG(L_CRIT, "ERROR: lump_check_opt: null send socket\n"); \
503                                 return 1; /* we presume they are different :-) */ \
504                         } \
505                         if (msg->rcv.bind_address){ \
506                                 ip=&msg->rcv.bind_address->address; \
507                                 port=msg->rcv.bind_address->port_no; \
508                                 proto=msg->rcv.bind_address->proto; \
509                         }else{ \
510                                 ip=&msg->rcv.dst_ip; \
511                                 port=msg->rcv.dst_port; \
512                                 proto=msg->rcv.proto; \
513                         } \
514
515         switch(l->u.cond){
516                 case COND_FALSE:
517                         return 0;
518                 case COND_TRUE:
519                         LUMP_SET_COND_TRUE(l);
520                         return 1;
521                 case COND_IF_DIFF_REALMS:
522                         get_ip_port_proto;
523                         /* faster tests first */
524                         if ((port==snd_i->send_sock->port_no) && 
525                                         (proto==snd_i->send_sock->proto) &&
526 #ifdef USE_COMP
527                                         (msg->rcv.comp==snd_i->comp) &&
528 #endif
529                                         (ip_addr_cmp(ip, &snd_i->send_sock->address)))
530                                 return 0;
531                         else {
532                                 LUMP_SET_COND_TRUE(l);
533                                 return 1;
534                         }
535                 case COND_IF_DIFF_AF:
536                         get_ip_port_proto;
537                         if (ip->af!=snd_i->send_sock->address.af) {
538                                 LUMP_SET_COND_TRUE(l);
539                                 return 1;
540                         } else return 0;
541                 case COND_IF_DIFF_PROTO:
542                         get_ip_port_proto;
543                         if (proto!=snd_i->send_sock->proto) {
544                                 LUMP_SET_COND_TRUE(l);
545                                 return 1;
546                         } else return 0;
547                 case COND_IF_DIFF_PORT:
548                         get_ip_port_proto;
549                         if (port!=snd_i->send_sock->port_no) {
550                                 LUMP_SET_COND_TRUE(l);
551                                 return 1;
552                         } else return 0;
553                 case COND_IF_DIFF_IP:
554                         get_ip_port_proto;
555                         if (ip_addr_cmp(ip, &snd_i->send_sock->address)) return 0;
556                         else {
557                                 LUMP_SET_COND_TRUE(l);
558                                 return 1;
559                         }
560                 case COND_IF_RAND:
561                         if(rand()>=RAND_MAX/2) {
562                                 LUMP_SET_COND_TRUE(l);
563                                 return 1;
564                         } else return 0;
565                 default:
566                         LOG(L_CRIT, "BUG: lump:w_check_opt: unknown lump condition %d\n",
567                                         l->u.cond);
568         }
569         return 0; /* false */
570 }
571
572
573
574 /* computes the "unpacked" len of a lump list,
575    code moved from build_req_from_req */
576 static inline int lumps_len(struct sip_msg* msg, struct lump* lumps, 
577                                                                 struct dest_info* send_info)
578 {
579         int s_offset;
580         int new_len;
581         struct lump* t;
582         struct lump* r;
583         str* send_address_str;
584         str* send_port_str;
585         struct socket_info* send_sock;
586         
587
588 #ifdef USE_COMP
589         #define RCVCOMP_LUMP_LEN \
590                                                 /* add;comp=xxx */ \
591                                         switch(msg->rcv.comp){ \
592                                                 case COMP_NONE: \
593                                                                 break; \
594                                                 case COMP_SIGCOMP: \
595                                                                 new_len+=COMP_PARAM_LEN+SIGCOMP_NAME_LEN; \
596                                                                 break; \
597                                                 case COMP_SERGZ: \
598                                                                 new_len+=COMP_PARAM_LEN+SERGZ_NAME_LEN ; \
599                                                                 break; \
600                                                 default: \
601                                                 LOG(L_CRIT, "BUG: lumps_len: unknown comp %d\n", \
602                                                                 msg->rcv.comp); \
603                                         }
604
605         #define SENDCOMP_LUMP_LEN \
606                                         /* add;comp=xxx */ \
607                                         switch(send_info->comp){ \
608                                                 case COMP_NONE: \
609                                                                 break; \
610                                                 case COMP_SIGCOMP: \
611                                                                 new_len+=COMP_PARAM_LEN+SIGCOMP_NAME_LEN; \
612                                                                 break; \
613                                                 case COMP_SERGZ: \
614                                                                 new_len+=COMP_PARAM_LEN+SERGZ_NAME_LEN ; \
615                                                                 break; \
616                                                 default: \
617                                                 LOG(L_CRIT, "BUG: lumps_len: unknown comp %d\n", \
618                                                                 send_info->comp); \
619                                         }
620 #else
621         #define RCVCOMP_LUMP_LEN
622         #define SENDCOMP_LUMP_LEN
623 #endif /*USE_COMP */
624         
625 #define SUBST_LUMP_LEN(subst_l) \
626                 switch((subst_l)->u.subst){ \
627                         case SUBST_RCV_IP: \
628                                 if (msg->rcv.bind_address){ \
629                                         new_len+=msg->rcv.bind_address->address_str.len; \
630                                         if (msg->rcv.bind_address->address.af!=AF_INET) \
631                                                 new_len+=2; \
632                                 }else{ \
633                                         /* FIXME */ \
634                                         LOG(L_CRIT, "FIXME: null bind_address\n"); \
635                                 }; \
636                                 break; \
637                         case SUBST_RCV_PORT: \
638                                 if (msg->rcv.bind_address){ \
639                                         new_len+=msg->rcv.bind_address->port_no_str.len; \
640                                 }else{ \
641                                         /* FIXME */ \
642                                         LOG(L_CRIT, "FIXME: null bind_address\n"); \
643                                 }; \
644                                 break; \
645                         case SUBST_RCV_PROTO: \
646                                 if (msg->rcv.bind_address){ \
647                                         switch(msg->rcv.bind_address->proto){ \
648                                                 case PROTO_NONE: \
649                                                 case PROTO_UDP: \
650                                                 case PROTO_TCP: \
651                                                 case PROTO_TLS: \
652                                                                 new_len+=3; \
653                                                                 break; \
654                                                 case PROTO_SCTP: \
655                                                                 new_len+=4; \
656                                                                 break; \
657                                                 default: \
658                                                 LOG(L_CRIT, "BUG: lumps_len: unknown proto %d\n", \
659                                                                 msg->rcv.bind_address->proto); \
660                                         }\
661                                 }else{ \
662                                         /* FIXME */ \
663                                         LOG(L_CRIT, "FIXME: null bind_address\n"); \
664                                 }; \
665                                 break; \
666                         case SUBST_RCV_ALL: \
667                                 if (msg->rcv.bind_address){ \
668                                         new_len+=msg->rcv.bind_address->address_str.len; \
669                                         if (msg->rcv.bind_address->address.af!=AF_INET) \
670                                                 new_len+=2; \
671                                         if (msg->rcv.bind_address->port_no!=SIP_PORT){ \
672                                                 /* add :port_no */ \
673                                                 new_len+=1+msg->rcv.bind_address->port_no_str.len; \
674                                         }\
675                                                 /*add;transport=xxx*/ \
676                                         switch(msg->rcv.bind_address->proto){ \
677                                                 case PROTO_NONE: \
678                                                 case PROTO_UDP: \
679                                                                 break; /* udp is the default */ \
680                                                 case PROTO_TCP: \
681                                                 case PROTO_TLS: \
682                                                                 new_len+=TRANSPORT_PARAM_LEN+3; \
683                                                                 break; \
684                                                 case PROTO_SCTP: \
685                                                                 new_len+=TRANSPORT_PARAM_LEN+4; \
686                                                                 break; \
687                                                 default: \
688                                                 LOG(L_CRIT, "BUG: lumps_len: unknown proto %d\n", \
689                                                                 msg->rcv.bind_address->proto); \
690                                         }\
691                                         RCVCOMP_LUMP_LEN \
692                                 }else{ \
693                                         /* FIXME */ \
694                                         LOG(L_CRIT, "FIXME: null bind_address\n"); \
695                                 }; \
696                                 break; \
697                         case SUBST_SND_IP: \
698                                 if (send_sock){ \
699                                         new_len+=send_address_str->len; \
700                                         if (send_sock->address.af!=AF_INET && \
701                                                         send_address_str==&(send_sock->address_str)) \
702                                                 new_len+=2; \
703                                 }else{ \
704                                         LOG(L_CRIT, "FIXME: lumps_len called with" \
705                                                         " null send_sock\n"); \
706                                 }; \
707                                 break; \
708                         case SUBST_SND_PORT: \
709                                 if (send_sock){ \
710                                         new_len+=send_port_str->len; \
711                                 }else{ \
712                                         LOG(L_CRIT, "FIXME: lumps_len called with" \
713                                                         " null send_sock\n"); \
714                                 }; \
715                                 break; \
716                         case SUBST_SND_PROTO: \
717                                 if (send_sock){ \
718                                         switch(send_sock->proto){ \
719                                                 case PROTO_NONE: \
720                                                 case PROTO_UDP: \
721                                                 case PROTO_TCP: \
722                                                 case PROTO_TLS: \
723                                                                 new_len+=3; \
724                                                                 break; \
725                                                 case PROTO_SCTP: \
726                                                                 new_len+=4; \
727                                                                 break; \
728                                                 default: \
729                                                 LOG(L_CRIT, "BUG: lumps_len: unknown proto %d\n", \
730                                                                 send_sock->proto); \
731                                         }\
732                                 }else{ \
733                                         LOG(L_CRIT, "FIXME: lumps_len called with" \
734                                                         " null send_sock\n"); \
735                                 }; \
736                                 break; \
737                         case SUBST_SND_ALL: \
738                                 if (send_sock){ \
739                                         new_len+=send_address_str->len; \
740                                         if ((send_sock->address.af!=AF_INET) && \
741                                                         (send_address_str==&(send_sock->address_str))) \
742                                                 new_len+=2; \
743                                         if ((send_sock->port_no!=SIP_PORT) || \
744                                                         (send_port_str!=&(send_sock->port_no_str))){ \
745                                                 /* add :port_no */ \
746                                                 new_len+=1+send_port_str->len; \
747                                         }\
748                                         /*add;transport=xxx*/ \
749                                         switch(send_sock->proto){ \
750                                                 case PROTO_NONE: \
751                                                 case PROTO_UDP: \
752                                                                 break; /* udp is the default */ \
753                                                 case PROTO_TCP: \
754                                                 case PROTO_TLS: \
755                                                                 new_len+=TRANSPORT_PARAM_LEN+3; \
756                                                                 break; \
757                                                 case PROTO_SCTP: \
758                                                                 new_len+=TRANSPORT_PARAM_LEN+4; \
759                                                                 break; \
760                                                 default: \
761                                                 LOG(L_CRIT, "BUG: lumps_len: unknown proto %d\n", \
762                                                                 send_sock->proto); \
763                                         }\
764                                         SENDCOMP_LUMP_LEN \
765                                 }else{ \
766                                         /* FIXME */ \
767                                         LOG(L_CRIT, "FIXME: lumps_len called with" \
768                                                         " null send_sock\n"); \
769                                 }; \
770                                 break; \
771                         case SUBST_NOP: /* do nothing */ \
772                                 break; \
773                         default: \
774                                 LOG(L_CRIT, "BUG: unknown subst type %d\n", \
775                                                 (subst_l)->u.subst); \
776                 }
777         
778         if (send_info){
779                 send_sock=send_info->send_sock;
780         }else{
781                 send_sock=0;
782         };
783         s_offset=0;
784         new_len=0;
785         /* init send_address_str & send_port_str */
786         if (msg->set_global_address.len)
787                 send_address_str=&(msg->set_global_address);
788         else
789                 send_address_str=&(send_sock->address_str);
790         if (msg->set_global_port.len)
791                 send_port_str=&(msg->set_global_port);
792         else
793                 send_port_str=&(send_sock->port_no_str);
794
795
796         for(t=lumps;t;t=t->next){
797                 /* skip if this is an OPT lump and the condition is not satisfied */
798                 if ((t->op==LUMP_ADD_OPT)&& !lump_check_opt(t, msg, send_info))
799                         continue;
800                 for(r=t->before;r;r=r->before){
801                         switch(r->op){
802                                 case LUMP_ADD:
803                                         new_len+=r->len;
804                                         break;
805                                 case LUMP_ADD_SUBST:
806                                         SUBST_LUMP_LEN(r);
807                                         break;
808                                 case LUMP_ADD_OPT:
809                                         /* skip if this is an OPT lump and the condition is
810                                          * not satisfied */
811                                         if (!lump_check_opt(r, msg, send_info))
812                                                 goto skip_before;
813                                         break;
814                                 default:
815                                         /* only ADD allowed for before/after */
816                                                 LOG(L_CRIT, "BUG: lumps_len: invalid op "
817                                                         "for data lump (%x)\n", r->op);
818                         }
819                 }
820 skip_before:
821                 switch(t->op){
822                         case LUMP_ADD:
823                                 new_len+=t->len;
824                                 break;
825                         case LUMP_ADD_SUBST:
826                                 SUBST_LUMP_LEN(t);
827                                 break;
828                         case LUMP_ADD_OPT:
829                                 /* we don't do anything here, it's only a condition for
830                                  * before & after */
831                                 break;
832                         case LUMP_DEL:
833                                 /* fix overlapping deleted zones */
834                                 if (t->u.offset < s_offset){
835                                         /* change len */
836                                         if (t->len>s_offset-t->u.offset)
837                                                         t->len-=s_offset-t->u.offset;
838                                         else t->len=0;
839                                         t->u.offset=s_offset;
840                                 }
841                                 s_offset=t->u.offset+t->len;
842                                 new_len-=t->len;
843                                 break;
844                         case LUMP_NOP:
845                                 /* fix offset if overlapping on a deleted zone */
846                                 if (t->u.offset < s_offset){
847                                         t->u.offset=s_offset;
848                                 }else
849                                         s_offset=t->u.offset;
850                                 /* do nothing */
851                                 break;
852                         default:
853                                 LOG(L_CRIT,"BUG:lumps_len: invalid"
854                                                         " op for data lump (%x)\n", r->op);
855                 }
856                 for (r=t->after;r;r=r->after){
857                         switch(r->op){
858                                 case LUMP_ADD:
859                                         new_len+=r->len;
860                                         break;
861                                 case LUMP_ADD_SUBST:
862                                         SUBST_LUMP_LEN(r);
863                                         break;
864                                 case LUMP_ADD_OPT:
865                                         /* skip if this is an OPT lump and the condition is
866                                          * not satisfied */
867                                         if (!lump_check_opt(r, msg, send_info))
868                                                 goto skip_after;
869                                         break;
870                                 default:
871                                         /* only ADD allowed for before/after */
872                                         LOG(L_CRIT, "BUG:lumps_len: invalid"
873                                                                 " op for data lump (%x)\n", r->op);
874                         }
875                 }
876 skip_after:
877                 ; /* to make gcc 3.* happy */
878         }
879         return new_len;
880 #undef RCVCOMP_LUMP_LEN
881 #undef SENDCOMP_LUMP_LEN
882 }
883
884
885
886 /* another helper functions, adds/Removes the lump,
887         code moved form build_req_from_req  */
888
889 static inline void process_lumps(       struct sip_msg* msg,
890                                                                         struct lump* lumps,
891                                                                         char* new_buf,
892                                                                         unsigned int* new_buf_offs,
893                                                                         unsigned int* orig_offs,
894                                                                         struct dest_info* send_info)
895 {
896         struct lump *t;
897         struct lump *r;
898         char* orig;
899         int size;
900         int offset;
901         int s_offset;
902         str* send_address_str;
903         str* send_port_str;
904         struct socket_info* send_sock;
905
906 #ifdef USE_COMP
907         #define RCVCOMP_PARAM_ADD \
908                                 /* add ;comp=xxxx */ \
909                                 switch(msg->rcv.comp){ \
910                                         case COMP_NONE: \
911                                                 break; \
912                                         case COMP_SIGCOMP: \
913                                                 memcpy(new_buf+offset, COMP_PARAM, COMP_PARAM_LEN);\
914                                                 offset+=COMP_PARAM_LEN; \
915                                                 memcpy(new_buf+offset, SIGCOMP_NAME, \
916                                                                 SIGCOMP_NAME_LEN); \
917                                                 offset+=SIGCOMP_NAME_LEN; \
918                                                 break; \
919                                         case COMP_SERGZ: \
920                                                 memcpy(new_buf+offset, COMP_PARAM, COMP_PARAM_LEN);\
921                                                 offset+=COMP_PARAM_LEN; \
922                                                 memcpy(new_buf+offset, SERGZ_NAME, SERGZ_NAME_LEN); \
923                                                 offset+=SERGZ_NAME_LEN; \
924                                                 break;\
925                                         default:\
926                                                 LOG(L_CRIT, "BUG: process_lumps: unknown comp %d\n", \
927                                                                 msg->rcv.comp); \
928                                 }
929         
930         #define SENDCOMP_PARAM_ADD \
931                                 /* add ;comp=xxxx */ \
932                                 switch(send_info->comp){ \
933                                         case COMP_NONE: \
934                                                 break; \
935                                         case COMP_SIGCOMP: \
936                                                 memcpy(new_buf+offset, COMP_PARAM, COMP_PARAM_LEN);\
937                                                 offset+=COMP_PARAM_LEN; \
938                                                 memcpy(new_buf+offset, SIGCOMP_NAME, \
939                                                                 SIGCOMP_NAME_LEN); \
940                                                 offset+=SIGCOMP_NAME_LEN; \
941                                                 break; \
942                                         case COMP_SERGZ: \
943                                                 memcpy(new_buf+offset, COMP_PARAM, COMP_PARAM_LEN);\
944                                                 offset+=COMP_PARAM_LEN; \
945                                                 memcpy(new_buf+offset, SERGZ_NAME, SERGZ_NAME_LEN); \
946                                                 offset+=SERGZ_NAME_LEN; \
947                                                 break;\
948                                         default:\
949                                                 LOG(L_CRIT, "BUG: process_lumps: unknown comp %d\n", \
950                                                                 msg->rcv.comp); \
951                                 } 
952 #else
953         #define RCVCOMP_PARAM_ADD
954         #define SENDCOMP_PARAM_ADD
955 #endif /* USE_COMP */
956
957 #define SUBST_LUMP(subst_l) \
958         switch((subst_l)->u.subst){ \
959                 case SUBST_RCV_IP: \
960                         if (msg->rcv.bind_address){  \
961                                 if (msg->rcv.bind_address->address.af!=AF_INET){\
962                                         new_buf[offset]='['; offset++; \
963                                 }\
964                                 memcpy(new_buf+offset, msg->rcv.bind_address->address_str.s, \
965                                                 msg->rcv.bind_address->address_str.len); \
966                                 offset+=msg->rcv.bind_address->address_str.len; \
967                                 if (msg->rcv.bind_address->address.af!=AF_INET){\
968                                         new_buf[offset]=']'; offset++; \
969                                 }\
970                         }else{  \
971                                 /*FIXME*/ \
972                                 LOG(L_CRIT, "FIXME: process_lumps: null bind_address\n"); \
973                         }; \
974                         break; \
975                 case SUBST_RCV_PORT: \
976                         if (msg->rcv.bind_address){  \
977                                 memcpy(new_buf+offset, msg->rcv.bind_address->port_no_str.s, \
978                                                 msg->rcv.bind_address->port_no_str.len); \
979                                 offset+=msg->rcv.bind_address->port_no_str.len; \
980                         }else{  \
981                                 /*FIXME*/ \
982                                 LOG(L_CRIT, "FIXME: process_lumps: null bind_address\n"); \
983                         }; \
984                         break; \
985                 case SUBST_RCV_ALL: \
986                         if (msg->rcv.bind_address){  \
987                                 /* address */ \
988                                 if (msg->rcv.bind_address->address.af!=AF_INET){\
989                                         new_buf[offset]='['; offset++; \
990                                 }\
991                                 memcpy(new_buf+offset, msg->rcv.bind_address->address_str.s, \
992                                                 msg->rcv.bind_address->address_str.len); \
993                                 offset+=msg->rcv.bind_address->address_str.len; \
994                                 if (msg->rcv.bind_address->address.af!=AF_INET){\
995                                         new_buf[offset]=']'; offset++; \
996                                 }\
997                                 /* :port */ \
998                                 if (msg->rcv.bind_address->port_no!=SIP_PORT){ \
999                                         new_buf[offset]=':'; offset++; \
1000                                         memcpy(new_buf+offset, \
1001                                                         msg->rcv.bind_address->port_no_str.s, \
1002                                                         msg->rcv.bind_address->port_no_str.len); \
1003                                         offset+=msg->rcv.bind_address->port_no_str.len; \
1004                                 }\
1005                                 switch(msg->rcv.bind_address->proto){ \
1006                                         case PROTO_NONE: \
1007                                         case PROTO_UDP: \
1008                                                 break; /* nothing to do, udp is default*/ \
1009                                         case PROTO_TCP: \
1010                                                 memcpy(new_buf+offset, TRANSPORT_PARAM, \
1011                                                                 TRANSPORT_PARAM_LEN); \
1012                                                 offset+=TRANSPORT_PARAM_LEN; \
1013                                                 memcpy(new_buf+offset, "tcp", 3); \
1014                                                 offset+=3; \
1015                                                 break; \
1016                                         case PROTO_TLS: \
1017                                                 memcpy(new_buf+offset, TRANSPORT_PARAM, \
1018                                                                 TRANSPORT_PARAM_LEN); \
1019                                                 offset+=TRANSPORT_PARAM_LEN; \
1020                                                 memcpy(new_buf+offset, "tls", 3); \
1021                                                 offset+=3; \
1022                                                 break; \
1023                                         case PROTO_SCTP: \
1024                                                 memcpy(new_buf+offset, TRANSPORT_PARAM, \
1025                                                                 TRANSPORT_PARAM_LEN); \
1026                                                 offset+=TRANSPORT_PARAM_LEN; \
1027                                                 memcpy(new_buf+offset, "sctp", 4); \
1028                                                 offset+=4; \
1029                                                 break; \
1030                                         default: \
1031                                                 LOG(L_CRIT, "BUG: process_lumps: unknown proto %d\n", \
1032                                                                 msg->rcv.bind_address->proto); \
1033                                 } \
1034                                 RCVCOMP_PARAM_ADD \
1035                         }else{  \
1036                                 /*FIXME*/ \
1037                                 LOG(L_CRIT, "FIXME: process_lumps: null bind_address\n"); \
1038                         }; \
1039                         break; \
1040                 case SUBST_SND_IP: \
1041                         if (send_sock){  \
1042                                 if ((send_sock->address.af!=AF_INET) && \
1043                                                 (send_address_str==&(send_sock->address_str))){\
1044                                         new_buf[offset]='['; offset++; \
1045                                 }\
1046                                 memcpy(new_buf+offset, send_address_str->s, \
1047                                                                         send_address_str->len); \
1048                                 offset+=send_address_str->len; \
1049                                 if ((send_sock->address.af!=AF_INET) && \
1050                                                 (send_address_str==&(send_sock->address_str))){\
1051                                         new_buf[offset]=']'; offset++; \
1052                                 }\
1053                         }else{  \
1054                                 /*FIXME*/ \
1055                                 LOG(L_CRIT, "FIXME: process_lumps: called with" \
1056                                                         " null send_sock\n"); \
1057                         }; \
1058                         break; \
1059                 case SUBST_SND_PORT: \
1060                         if (send_sock){  \
1061                                 memcpy(new_buf+offset, send_port_str->s, \
1062                                                                         send_port_str->len); \
1063                                 offset+=send_port_str->len; \
1064                         }else{  \
1065                                 /*FIXME*/ \
1066                                 LOG(L_CRIT, "FIXME: process_lumps: called with" \
1067                                                 " null send_sock\n"); \
1068                         }; \
1069                         break; \
1070                 case SUBST_SND_ALL: \
1071                         if (send_sock){  \
1072                                 /* address */ \
1073                                 if ((send_sock->address.af!=AF_INET) && \
1074                                                 (send_address_str==&(send_sock->address_str))){\
1075                                         new_buf[offset]='['; offset++; \
1076                                 }\
1077                                 memcpy(new_buf+offset, send_address_str->s, \
1078                                                 send_address_str->len); \
1079                                 offset+=send_address_str->len; \
1080                                 if ((send_sock->address.af!=AF_INET) && \
1081                                                 (send_address_str==&(send_sock->address_str))){\
1082                                         new_buf[offset]=']'; offset++; \
1083                                 }\
1084                                 /* :port */ \
1085                                 if ((send_sock->port_no!=SIP_PORT) || \
1086                                         (send_port_str!=&(send_sock->port_no_str))){ \
1087                                         new_buf[offset]=':'; offset++; \
1088                                         memcpy(new_buf+offset, send_port_str->s, \
1089                                                         send_port_str->len); \
1090                                         offset+=send_port_str->len; \
1091                                 }\
1092                                 switch(send_sock->proto){ \
1093                                         case PROTO_NONE: \
1094                                         case PROTO_UDP: \
1095                                                 break; /* nothing to do, udp is default*/ \
1096                                         case PROTO_TCP: \
1097                                                 memcpy(new_buf+offset, TRANSPORT_PARAM, \
1098                                                                 TRANSPORT_PARAM_LEN); \
1099                                                 offset+=TRANSPORT_PARAM_LEN; \
1100                                                 memcpy(new_buf+offset, "tcp", 3); \
1101                                                 offset+=3; \
1102                                                 break; \
1103                                         case PROTO_TLS: \
1104                                                 memcpy(new_buf+offset, TRANSPORT_PARAM, \
1105                                                                 TRANSPORT_PARAM_LEN); \
1106                                                 offset+=TRANSPORT_PARAM_LEN; \
1107                                                 memcpy(new_buf+offset, "tls", 3); \
1108                                                 offset+=3; \
1109                                                 break; \
1110                                         case PROTO_SCTP: \
1111                                                 memcpy(new_buf+offset, TRANSPORT_PARAM, \
1112                                                                 TRANSPORT_PARAM_LEN); \
1113                                                 offset+=TRANSPORT_PARAM_LEN; \
1114                                                 memcpy(new_buf+offset, "sctp", 4); \
1115                                                 offset+=4; \
1116                                                 break; \
1117                                         default: \
1118                                                 LOG(L_CRIT, "BUG: process_lumps: unknown proto %d\n", \
1119                                                                 send_sock->proto); \
1120                                 } \
1121                                 SENDCOMP_PARAM_ADD \
1122                         }else{  \
1123                                 /*FIXME*/ \
1124                                 LOG(L_CRIT, "FIXME: process_lumps: null bind_address\n"); \
1125                         }; \
1126                         break; \
1127                 case SUBST_RCV_PROTO: \
1128                         if (msg->rcv.bind_address){ \
1129                                 switch(msg->rcv.bind_address->proto){ \
1130                                         case PROTO_NONE: \
1131                                         case PROTO_UDP: \
1132                                                 memcpy(new_buf+offset, "udp", 3); \
1133                                                 offset+=3; \
1134                                                 break; \
1135                                         case PROTO_TCP: \
1136                                                 memcpy(new_buf+offset, "tcp", 3); \
1137                                                 offset+=3; \
1138                                                 break; \
1139                                         case PROTO_TLS: \
1140                                                 memcpy(new_buf+offset, "tls", 3); \
1141                                                 offset+=3; \
1142                                                 break; \
1143                                         case PROTO_SCTP: \
1144                                                 memcpy(new_buf+offset, "sctp", 4); \
1145                                                 offset+=4; \
1146                                                 break; \
1147                                         default: \
1148                                                 LOG(L_CRIT, "BUG: process_lumps: unknown proto %d\n", \
1149                                                                 msg->rcv.bind_address->proto); \
1150                                 } \
1151                         }else{  \
1152                                 /*FIXME*/ \
1153                                 LOG(L_CRIT, "FIXME: process_lumps: called with null" \
1154                                                         " send_sock \n"); \
1155                         }; \
1156                         break; \
1157                 case  SUBST_SND_PROTO: \
1158                         if (send_sock){ \
1159                                 switch(send_sock->proto){ \
1160                                         case PROTO_NONE: \
1161                                         case PROTO_UDP: \
1162                                                 memcpy(new_buf+offset, "udp", 3); \
1163                                                 offset+=3; \
1164                                                 break; \
1165                                         case PROTO_TCP: \
1166                                                 memcpy(new_buf+offset, "tcp", 3); \
1167                                                 offset+=3; \
1168                                                 break; \
1169                                         case PROTO_TLS: \
1170                                                 memcpy(new_buf+offset, "tls", 3); \
1171                                                 offset+=3; \
1172                                                 break; \
1173                                         case PROTO_SCTP: \
1174                                                 memcpy(new_buf+offset, "sctp", 4); \
1175                                                 offset+=4; \
1176                                                 break; \
1177                                         default: \
1178                                                 LOG(L_CRIT, "BUG: process_lumps: unknown proto %d\n", \
1179                                                                 send_sock->proto); \
1180                                 } \
1181                         }else{  \
1182                                 /*FIXME*/ \
1183                                 LOG(L_CRIT, "FIXME: process_lumps: called with null" \
1184                                                         " send_sock \n"); \
1185                         }; \
1186                         break; \
1187                 default: \
1188                                 LOG(L_CRIT, "BUG: process_lumps: unknown subst type %d\n", \
1189                                                         (subst_l)->u.subst); \
1190         }
1191
1192         if (send_info){
1193                 send_sock=send_info->send_sock;
1194         }else{
1195                 send_sock=0;
1196         }
1197         /* init send_address_str & send_port_str */
1198         if (msg->set_global_address.len)
1199                 send_address_str=&(msg->set_global_address);
1200         else
1201                 send_address_str=&(send_sock->address_str);
1202         if (msg->set_global_port.len)
1203                 send_port_str=&(msg->set_global_port);
1204         else
1205                 send_port_str=&(send_sock->port_no_str);
1206
1207
1208         orig=msg->buf;
1209         offset=*new_buf_offs;
1210         s_offset=*orig_offs;
1211
1212         for (t=lumps;t;t=t->next){
1213                 switch(t->op){
1214                         case LUMP_ADD:
1215                         case LUMP_ADD_SUBST:
1216                         case LUMP_ADD_OPT:
1217                                 /* skip if this is an OPT lump and the condition is
1218                                  * not satisfied */
1219                                 if ((t->op==LUMP_ADD_OPT) &&
1220                                                 (!lump_check_opt(t, msg, send_info)))
1221                                         continue;
1222                                 /* just add it here! */
1223                                 /* process before  */
1224                                 for(r=t->before;r;r=r->before){
1225                                         switch (r->op){
1226                                                 case LUMP_ADD:
1227                                                         /*just add it here*/
1228                                                         memcpy(new_buf+offset, r->u.value, r->len);
1229                                                         offset+=r->len;
1230                                                         break;
1231                                                 case LUMP_ADD_SUBST:
1232                                                         SUBST_LUMP(r);
1233                                                         break;
1234                                                 case LUMP_ADD_OPT:
1235                                                         /* skip if this is an OPT lump and the condition is
1236                                                         * not satisfied */
1237                                                         if (!lump_check_opt(r, msg, send_info))
1238                                                                 goto skip_before;
1239                                                         break;
1240                                                 default:
1241                                                         /* only ADD allowed for before/after */
1242                                                         LOG(L_CRIT, "BUG:process_lumps: "
1243                                                                         "invalid op for data lump (%x)\n", r->op);
1244                                         }
1245                                 }
1246 skip_before:
1247                                 /* copy "main" part */
1248                                 switch(t->op){
1249                                         case LUMP_ADD:
1250                                                 memcpy(new_buf+offset, t->u.value, t->len);
1251                                                 offset+=t->len;
1252                                                 break;
1253                                         case LUMP_ADD_SUBST:
1254                                                 SUBST_LUMP(t);
1255                                                 break;
1256                                         case LUMP_ADD_OPT:
1257                                                 /* do nothing, it's only a condition */
1258                                                 break;
1259                                         default:
1260                                                 /* should not ever get here */
1261                                                 LOG(L_CRIT, "BUG: process_lumps: unhandled data lump "
1262                                                                 " op %d\n", t->op);
1263                                 }
1264                                 /* process after */
1265                                 for(r=t->after;r;r=r->after){
1266                                         switch (r->op){
1267                                                 case LUMP_ADD:
1268                                                         /*just add it here*/
1269                                                         memcpy(new_buf+offset, r->u.value, r->len);
1270                                                         offset+=r->len;
1271                                                         break;
1272                                                 case LUMP_ADD_SUBST:
1273                                                         SUBST_LUMP(r);
1274                                                         break;
1275                                                 case LUMP_ADD_OPT:
1276                                                         /* skip if this is an OPT lump and the condition is
1277                                                         * not satisfied */
1278                                                         if (!lump_check_opt(r, msg, send_info))
1279                                                                 goto skip_after;
1280                                                         break;
1281                                                 default:
1282                                                         /* only ADD allowed for before/after */
1283                                                         LOG(L_CRIT, "BUG:process_lumps: "
1284                                                                         "invalid op for data lump (%x)\n", r->op);
1285                                         }
1286                                 }
1287 skip_after:
1288                                 break;
1289                         case LUMP_NOP:
1290                         case LUMP_DEL:
1291                                 /* copy till offset */
1292                                 if (s_offset>t->u.offset){
1293                                         DBG("Warning: (%d) overlapped lumps offsets,"
1294                                                 " ignoring(%x, %x)\n", t->op, s_offset,t->u.offset);
1295                                         /* this should've been fixed above (when computing len) */
1296                                         /* just ignore it*/
1297                                         break;
1298                                 }
1299                                 size=t->u.offset-s_offset;
1300                                 if (size){
1301                                         memcpy(new_buf+offset, orig+s_offset,size);
1302                                         offset+=size;
1303                                         s_offset+=size;
1304                                 }
1305                                 /* process before  */
1306                                 for(r=t->before;r;r=r->before){
1307                                         switch (r->op){
1308                                                 case LUMP_ADD:
1309                                                         /*just add it here*/
1310                                                         memcpy(new_buf+offset, r->u.value, r->len);
1311                                                         offset+=r->len;
1312                                                         break;
1313                                                 case LUMP_ADD_SUBST:
1314                                                         SUBST_LUMP(r);
1315                                                         break;
1316                                                 case LUMP_ADD_OPT:
1317                                                         /* skip if this is an OPT lump and the condition is
1318                                                         * not satisfied */
1319                                                         if (!lump_check_opt(r, msg, send_info))
1320                                                                 goto skip_nop_before;
1321                                                         break;
1322                                                 default:
1323                                                         /* only ADD allowed for before/after */
1324                                                         LOG(L_CRIT, "BUG:process_lumps: "
1325                                                                         "invalid op for data lump (%x)\n",r->op);
1326                                         }
1327                                 }
1328 skip_nop_before:
1329                                 /* process main (del only) */
1330                                 if (t->op==LUMP_DEL){
1331                                         /* skip len bytes from orig msg */
1332                                         s_offset+=t->len;
1333                                 }
1334                                 /* process after */
1335                                 for(r=t->after;r;r=r->after){
1336                                         switch (r->op){
1337                                                 case LUMP_ADD:
1338                                                         /*just add it here*/
1339                                                         memcpy(new_buf+offset, r->u.value, r->len);
1340                                                         offset+=r->len;
1341                                                         break;
1342                                                 case LUMP_ADD_SUBST:
1343                                                         SUBST_LUMP(r);
1344                                                         break;
1345                                                 case LUMP_ADD_OPT:
1346                                                         /* skip if this is an OPT lump and the condition is
1347                                                         * not satisfied */
1348                                                         if (!lump_check_opt(r, msg, send_info))
1349                                                                 goto skip_nop_after;
1350                                                         break;
1351                                                 default:
1352                                                         /* only ADD allowed for before/after */
1353                                                         LOG(L_CRIT, "BUG:process_lumps: "
1354                                                                         "invalid op for data lump (%x)\n", r->op);
1355                                         }
1356                                 }
1357 skip_nop_after:
1358                                 break;
1359                         default:
1360                                         LOG(L_CRIT, "BUG: process_lumps: "
1361                                                         "unknown op (%x)\n", t->op);
1362                 }
1363         }
1364         *new_buf_offs=offset;
1365         *orig_offs=s_offset;
1366 #undef RCVCOMP_PARAM_ADD 
1367 #undef SENDCOMP_PARAM_ADD
1368 }
1369
1370
1371 /*
1372  * Adjust/insert Content-Length if necessary
1373  */
1374 static inline int adjust_clen(struct sip_msg* msg, int body_delta, int proto)
1375 {
1376         struct lump* anchor;
1377         char* clen_buf;
1378         int clen_len, body_only;
1379 #ifdef USE_TCP
1380         char* body;
1381         int comp_clen;
1382 #endif /* USE_TCP */
1383
1384         /* Calculate message length difference caused by lumps modifying message
1385          * body, from this point on the message body must not be modified. Zero
1386          * value indicates that the body hasn't been modified
1387         */
1388
1389         clen_buf = 0;
1390         anchor=0;
1391         body_only=1;
1392
1393         /* check to see if we need to add clen */
1394 #ifdef USE_TCP
1395         if (proto == PROTO_TCP
1396 #ifdef USE_TLS
1397             || proto == PROTO_TLS
1398 #endif
1399             ) {
1400                 if (parse_headers(msg, HDR_CONTENTLENGTH_F, 0)==-1){
1401                         LOG(L_ERR, "adjust_clen: error parsing content-length\n");
1402                         goto error;
1403                 }
1404                 if (unlikely(msg->content_length==0)){
1405                         /* not present, we need to add it */
1406                         /* msg->unparsed should point just before the final crlf
1407                          * - whole message was parsed by the above parse_headers
1408                          *   which did not find content-length */
1409                         anchor=anchor_lump(msg, msg->unparsed-msg->buf, 0,
1410                                                                                                 HDR_CONTENTLENGTH_T);
1411                         if (anchor==0){
1412                                 LOG(L_ERR, "adjust_clen: cannot set clen anchor\n");
1413                                 goto error;
1414                         }
1415                         body_only=0;
1416                 }else{
1417                         /* compute current content length and compare it with the
1418                            one in the message */
1419                         body=get_body(msg);
1420                         if (unlikely(body==0)){
1421                                 ser_error=E_BAD_REQ;
1422                                 LOG(L_ERR, "adjust_clen: no message body found"
1423                                                 " (missing crlf?)");
1424                                 goto error;
1425                         }
1426                         comp_clen=msg->len-(int)(body-msg->buf)+body_delta;
1427                         if (comp_clen!=(int)(long)msg->content_length->parsed){
1428                                 /* note: we don't distinguish here between received with
1429                                    wrong content-length and content-length changed, we just
1430                                    fix it automatically in both cases (the reason being
1431                                    that an error message telling we have received a msg-
1432                                    with wrong content-length is of very little use) */
1433                                 anchor = del_lump(msg, msg->content_length->body.s-msg->buf,
1434                                                                         msg->content_length->body.len,
1435                                                                         HDR_CONTENTLENGTH_T);
1436                                 if (anchor==0) {
1437                                         LOG(L_ERR, "adjust_clen: Can't remove original"
1438                                                                 " Content-Length\n");
1439                                         goto error;
1440                                 }
1441                                 body_only=1;
1442                         }
1443                 }
1444         }else
1445 #endif /* USE_TCP */
1446         if (body_delta){
1447                 if (parse_headers(msg, HDR_CONTENTLENGTH_F, 0) == -1) {
1448                         LOG(L_ERR, "adjust_clen: Error parsing Content-Length\n");
1449                         goto error;
1450                 }
1451
1452                 /* The body has been changed, try to find
1453                  * existing Content-Length
1454                  */
1455                 /* no need for Content-Length if it's and UDP packet and
1456                  * it hasn't Content-Length already */
1457                 if ((msg->content_length==0)){
1458                     /* content-length doesn't exist, append it */
1459                         /* msg->unparsed should point just before the final crlf
1460                          * - whole message was parsed by the above parse_headers
1461                          *   which did not find content-length */
1462                         if (proto!=PROTO_UDP){
1463                                 anchor=anchor_lump(msg, msg->unparsed-msg->buf, 0,
1464                                                                                                         HDR_CONTENTLENGTH_T);
1465                                 if (anchor==0){
1466                                         LOG(L_ERR, "adjust_clen: cannot set clen anchor\n");
1467                                         goto error;
1468                                 }
1469                                 body_only=0;
1470                         } /* else
1471                                 DBG("adjust_clen: UDP packet with no clen => "
1472                                                 "not adding one \n"); */
1473                 }else{
1474                         /* Content-Length has been found, remove it */
1475                         anchor = del_lump(      msg, msg->content_length->body.s - msg->buf,
1476                                                                 msg->content_length->body.len,
1477                                                                 HDR_CONTENTLENGTH_T);
1478                         if (anchor==0) {
1479                                 LOG(L_ERR, "adjust_clen: Can't remove original"
1480                                                         " Content-Length\n");
1481                                 goto error;
1482                         }
1483                 }
1484         }
1485
1486         if (anchor){
1487                 clen_buf = clen_builder(msg, &clen_len, body_delta, body_only);
1488                 if (!clen_buf) goto error;
1489                 if (insert_new_lump_after(anchor, clen_buf, clen_len,
1490                                         HDR_CONTENTLENGTH_T) == 0)
1491                         goto error;
1492         }
1493         
1494         return 0;
1495 error:
1496         if (clen_buf) pkg_free(clen_buf);
1497         return -1;
1498 }
1499
1500
1501
1502 /** builds a request in memory from another sip request.
1503   *
1504   * Side-effects: - it adds lumps to the msg which are _not_ cleaned.
1505   * The added lumps are HDR_VIA_T (almost always added), HDR_CONTENLENGTH_T
1506   * and HDR_ROUTE_T (when a Route: header is added as a result of a non-null
1507   * msg->path_vec).
1508   *               - it might change send_info->proto and send_info->send_socket
1509   *                 if proto fallback is enabled (see below).
1510   *
1511   * Uses also global_req_flags ( OR'ed with msg->msg_flags, see send_info
1512   * below).
1513   *
1514   * @param msg  - sip message structure, complete with lumps
1515   * @param returned_len - result length (filled in)
1516   * @param send_info  - dest_info structure (value/result), contains where the
1517   *                     packet will be sent to (it's needed for building a 
1518   *                     correct via, fill RR lumps a.s.o.). If MTU based
1519   *                     protocol fall-back is enabled (see flags below),
1520   *                     send_info->proto might be updated with the new
1521   *                     protocol.
1522   *                     msg->msg_flags used:
1523   *                     - FL_TCP_MTU_FB, FL_TLS_MTU_FB and FL_SCTP_MTU_FB -
1524   *                       fallback to the corresp. proto if the built 
1525   *                       message > mtu and send_info->proto==PROTO_UDP. 
1526   *                       It will also update send_info->proto.
1527   *                     - FL_FORCE_RPORT: add rport to via
1528   * @param mode - flags for building the message, can be a combination of:
1529   *                 * BUILD_NO_LOCAL_VIA - don't add a local via
1530   *                 * BUILD_NO_VIA1_UPDATE - don't update first via (rport,
1531   *                    received a.s.o)
1532   *                 * BUILD_NO_PATH - don't add a Route: header with the 
1533   *                   msg->path_vec content.
1534   *                 * BUILD_IN_SHM - build the result in shm memory
1535   *
1536   * @return pointer to the new request (pkg_malloc'ed or shm_malloc'ed,
1537   * depending on the presence of the BUILD_IN_SHM flag, needs freeing when
1538   *   done) and sets returned_len or 0 on error.
1539   */
1540 char * build_req_buf_from_sip_req( struct sip_msg* msg,
1541                                                                 unsigned int *returned_len,
1542                                                                 struct dest_info* send_info,
1543                                                                 unsigned int mode)
1544 {
1545         unsigned int len, new_len, received_len, rport_len, uri_len, via_len,
1546                                  body_delta;
1547         char* line_buf;
1548         char* received_buf;
1549         char* rport_buf;
1550         char* new_buf;
1551         char* buf;
1552         str path_buf;
1553         unsigned int offset, s_offset, size;
1554         struct lump* via_anchor;
1555         struct lump* via_lump;
1556         struct lump* via_insert_param;
1557         struct lump* path_anchor;
1558         struct lump* path_lump;
1559         str branch;
1560         unsigned int flags;
1561         unsigned int udp_mtu;
1562         struct dest_info di;
1563
1564         via_insert_param=0;
1565         uri_len=0;
1566         buf=msg->buf;
1567         len=msg->len;
1568         received_len=0;
1569         rport_len=0;
1570         new_buf=0;
1571         received_buf=0;
1572         rport_buf=0;
1573         via_anchor=0;
1574         line_buf=0;
1575         via_len=0;
1576         path_buf.s=0;
1577         path_buf.len=0;
1578
1579         flags=msg->msg_flags|global_req_flags;
1580         /* Calculate message body difference and adjust Content-Length */
1581         body_delta = lumps_len(msg, msg->body_lumps, send_info);
1582         if (adjust_clen(msg, body_delta, send_info->proto) < 0) {
1583                 LOG(L_ERR, "ERROR: build_req_buf_from_sip_req: Error while adjusting"
1584                                 " Content-Length\n");
1585                 goto error00;
1586         }
1587
1588         if(unlikely(mode&BUILD_NO_LOCAL_VIA))
1589                 goto after_local_via;
1590
1591         /* create the via header */
1592         branch.s=msg->add_to_branch_s;
1593         branch.len=msg->add_to_branch_len;
1594
1595         via_anchor=anchor_lump(msg, msg->via1->hdr.s-buf, 0, HDR_VIA_T);
1596         if (unlikely(via_anchor==0)) goto error00;
1597         line_buf = create_via_hf( &via_len, msg, send_info, &branch);
1598         if (unlikely(!line_buf)){
1599                 LOG(L_ERR,"ERROR: build_req_buf_from_sip_req: "
1600                                         "memory allocation failure\n");
1601                 goto error00;
1602         }
1603 after_local_via:
1604         if(unlikely(mode&BUILD_NO_VIA1_UPDATE))
1605                 goto after_update_via1;
1606         /* check if received needs to be added */
1607         if ( received_test(msg) ) {
1608                 if ((received_buf=received_builder(msg,&received_len))==0){
1609                         LOG(L_ERR, "ERROR: build_req_buf_from_sip_req:"
1610                                                         " received_builder failed\n");
1611                         goto error01;  /* free also line_buf */
1612                 }
1613         }
1614
1615         /* check if rport needs to be updated:
1616          *  - if FL_FORCE_RPORT is set add it (and del. any previous version)
1617          *  - if via already contains an rport add it and overwrite the previous
1618          *  rport value if present (if you don't want to overwrite the previous
1619          *  version remove the comments) */
1620         if ((flags&FL_FORCE_RPORT)||
1621                         (msg->via1->rport /*&& msg->via1->rport->value.s==0*/)){
1622                 if ((rport_buf=rport_builder(msg, &rport_len))==0){
1623                         LOG(L_ERR, "ERROR: build_req_buf_from_sip_req:"
1624                                                         " rport_builder failed\n");
1625                         goto error01; /* free everything */
1626                 }
1627         }
1628
1629         /* find out where the offset of the first parameter that should be added
1630          * (after host:port), needed by add receive & maybe rport */
1631         if (msg->via1->params.s){
1632                         size= msg->via1->params.s-msg->via1->hdr.s-1; /*compensate
1633                                                                                                                   for ';' */
1634         }else{
1635                         size= msg->via1->host.s-msg->via1->hdr.s+msg->via1->host.len;
1636                         if (msg->via1->port!=0){
1637                                 /*size+=strlen(msg->via1->hdr.s+size+1)+1;*/
1638                                 size += msg->via1->port_str.len + 1; /* +1 for ':'*/
1639                         }
1640 #if 0
1641                         /* no longer necessary, now hots.s contains [] */
1642                 #ifdef USE_IPV6
1643                         if(send_sock->address.af==AF_INET6) size+=1; /* +1 for ']'*/
1644                 #endif
1645 #endif
1646         }
1647         /* if received needs to be added, add anchor after host and add it, or
1648          * overwrite the previous one if already present */
1649         if (received_len){
1650                 if (msg->via1->received){ /* received already present => overwrite it*/
1651                         via_insert_param=del_lump(msg,
1652                                                                 msg->via1->received->start-buf-1, /*;*/
1653                                                                 msg->via1->received->size+1, /*;*/ HDR_VIA_T);
1654                 }else if (via_insert_param==0){ /* receive not present, ok */
1655                         via_insert_param=anchor_lump(msg, msg->via1->hdr.s-buf+size, 0,
1656                                                                                         HDR_VIA_T);
1657                 }
1658                 if (via_insert_param==0) goto error02; /* free received_buf */
1659                 if (insert_new_lump_after(via_insert_param, received_buf, received_len,
1660                                         HDR_VIA_T) ==0 ) goto error02; /* free received_buf */
1661         }
1662         /* if rport needs to be updated, delete it if present and add it's value */
1663         if (rport_len){
1664                 if (msg->via1->rport){ /* rport already present */
1665                         via_insert_param=del_lump(msg,
1666                                                                 msg->via1->rport->start-buf-1, /*';'*/
1667                                                                 msg->via1->rport->size+1 /* ; */, HDR_VIA_T);
1668                 }else if (via_insert_param==0){ /*force rport, no rport present */
1669                         /* no rport, add it */
1670                         via_insert_param=anchor_lump(msg, msg->via1->hdr.s-buf+size, 0,
1671                                                                                         HDR_VIA_T);
1672                 }
1673                 if (via_insert_param==0) goto error03; /* free rport_buf */
1674                 if (insert_new_lump_after(via_insert_param, rport_buf, rport_len,
1675                                                                         HDR_VIA_T) ==0 )
1676                         goto error03; /* free rport_buf */
1677
1678         }
1679
1680 after_update_via1:
1681         /* add route with path content */
1682         if(unlikely(!(mode&BUILD_NO_PATH) && msg->path_vec.s &&
1683                                         msg->path_vec.len)){
1684                 path_buf.len=ROUTE_PREFIX_LEN+msg->path_vec.len+CRLF_LEN;
1685                 path_buf.s=pkg_malloc(path_buf.len+1);
1686                 if (unlikely(path_buf.s==0)){
1687                         LOG(L_ERR, "out of memory\n");
1688                         ser_error=E_OUT_OF_MEM;
1689                         goto error00;
1690                 }
1691                 memcpy(path_buf.s, ROUTE_PREFIX, ROUTE_PREFIX_LEN);
1692                 memcpy(path_buf.s+ROUTE_PREFIX_LEN, msg->path_vec.s,
1693                                         msg->path_vec.len);
1694                 memcpy(path_buf.s+ROUTE_PREFIX_LEN+msg->path_vec.len, CRLF, CRLF_LEN);
1695                 path_buf.s[path_buf.len]=0;
1696                 /* insert Route header either before the other routes
1697                    (if present & parsed), after the local via or after in front of
1698                     the first via if we don't add a local via*/
1699                 if (msg->route){
1700                         path_anchor=anchor_lump(msg, msg->route->name.s-buf, 0, 
1701                                                                         HDR_ROUTE_T);
1702                 }else if (likely(via_anchor)){
1703                         path_anchor=via_anchor;
1704                 }else if (likely(msg->via1)){
1705                         path_anchor=anchor_lump(msg, msg->via1->hdr.s-buf, 0, 
1706                                                                         HDR_ROUTE_T);
1707                 }else{
1708                         /* if no via1 (theoretically possible for non-sip messages,
1709                            e.g. http xmlrpc) */
1710                         path_anchor=anchor_lump(msg, msg->headers->name.s-buf, 0, 
1711                                                                         HDR_ROUTE_T);
1712                 }
1713                 if (unlikely(path_anchor==0))
1714                         goto error05;
1715                 if (unlikely((path_lump=insert_new_lump_after(path_anchor, path_buf.s,
1716                                                                                                                 path_buf.len,
1717                                                                                                                 HDR_ROUTE_T))==0))
1718                         goto error05;
1719         }
1720         /* compute new msg len and fix overlapping zones*/
1721         new_len=len+body_delta+lumps_len(msg, msg->add_rm, send_info)+via_len;
1722 #ifdef XL_DEBUG
1723         LOG(L_ERR, "DEBUG: new_len(%d)=len(%d)+lumps_len\n", new_len, len);
1724 #endif
1725         udp_mtu=cfg_get(core, core_cfg, udp_mtu);
1726         di.proto=PROTO_NONE;
1727         if (unlikely((send_info->proto==PROTO_UDP) && udp_mtu && 
1728                                         (flags & FL_MTU_FB_MASK) && (new_len>udp_mtu)
1729                                         && (!(mode&BUILD_NO_LOCAL_VIA)))){
1730
1731                 di=*send_info; /* copy whole struct - will be used in the Via builder */
1732                 di.proto=PROTO_NONE; /* except the proto */
1733 #ifdef USE_TCP
1734                 if (!tcp_disable && (flags & FL_MTU_TCP_FB) &&
1735                                 (di.send_sock=get_send_socket(msg, &send_info->to, PROTO_TCP))){
1736                         di.proto=PROTO_TCP;
1737                 }
1738         #ifdef USE_TLS
1739                 else if (!tls_disable && (flags & FL_MTU_TLS_FB) &&
1740                                 (di.send_sock=get_send_socket(msg, &send_info->to, PROTO_TLS))){
1741                         di.proto=PROTO_TLS;
1742                 }
1743         #endif /* USE_TLS */
1744 #endif /* USE_TCP */
1745 #ifdef USE_SCTP
1746         #ifdef USE_TCP
1747                 else
1748         #endif /* USE_TCP */
1749                  if (!sctp_disable && (flags & FL_MTU_SCTP_FB) &&
1750                                 (di.send_sock=get_send_socket(msg, &send_info->to, PROTO_SCTP))){
1751                         di.proto=PROTO_SCTP;
1752                  }
1753 #endif /* USE_SCTP */
1754                 
1755                 if (di.proto!=PROTO_NONE){
1756                         new_len-=via_len;
1757                         if(likely(line_buf)) pkg_free(line_buf);
1758                         line_buf = create_via_hf( &via_len, msg, &di, &branch);
1759                         if (!line_buf){
1760                                 LOG(L_ERR,"ERROR: build_req_buf_from_sip_req: "
1761                                                         "memory allocation failure!\n");
1762                                 goto error00;
1763                         }
1764                         new_len+=via_len;
1765                 }
1766         }
1767         /* add via header to the list */
1768         /* try to add it before msg. 1st via */
1769         /* add first via, as an anchor for second via*/
1770         if(likely(line_buf)) {
1771                 if ((via_lump=insert_new_lump_before(via_anchor, line_buf, via_len,
1772                                                                                         HDR_VIA_T))==0)
1773                         goto error04;
1774         }
1775         if (msg->new_uri.s){
1776                 uri_len=msg->new_uri.len;
1777                 new_len=new_len-msg->first_line.u.request.uri.len+uri_len;
1778         }
1779         if(unlikely(mode&BUILD_IN_SHM))
1780                 new_buf=(char*)shm_malloc(new_len+1);
1781         else
1782                 new_buf=(char*)pkg_malloc(new_len+1);
1783         if (new_buf==0){
1784                 ser_error=E_OUT_OF_MEM;
1785                 LOG(L_ERR, "ERROR: build_req_buf_from_sip_req: out of memory\n");
1786                 goto error00;
1787         }
1788
1789         offset=s_offset=0;
1790         if (msg->new_uri.s){
1791                 /* copy message up to uri */
1792                 size=msg->first_line.u.request.uri.s-buf;
1793                 memcpy(new_buf, buf, size);
1794                 offset+=size;
1795                 s_offset+=size;
1796                 /* add our uri */
1797                 memcpy(new_buf+offset, msg->new_uri.s, uri_len);
1798                 offset+=uri_len;
1799                 s_offset+=msg->first_line.u.request.uri.len; /* skip original uri */
1800         }
1801         new_buf[new_len]=0;
1802         /* copy msg adding/removing lumps */
1803         process_lumps(msg, msg->add_rm, new_buf, &offset, &s_offset, send_info);
1804         process_lumps(msg, msg->body_lumps, new_buf, &offset, &s_offset,send_info);
1805         /* copy the rest of the message */
1806         memcpy(new_buf+offset, buf+s_offset, len-s_offset);
1807         new_buf[new_len]=0;
1808
1809         /* update the send_info if udp_mtu affected */
1810         if (di.proto!=PROTO_NONE) { 
1811                 send_info->proto=di.proto;
1812                 send_info->send_sock=di.send_sock;
1813         }
1814
1815 #ifdef DBG_MSG_QA
1816         if (new_buf[new_len-1]==0) {
1817                 LOG(L_ERR, "ERROR: build_req_buf_from_sip_req: 0 in the end\n");
1818                 abort();
1819         }
1820 #endif
1821
1822         *returned_len=new_len;
1823         return new_buf;
1824
1825 error01:
1826 error02:
1827         if (received_buf) pkg_free(received_buf);
1828 error03:
1829         if (rport_buf) pkg_free(rport_buf);
1830 error04:
1831         if (line_buf) pkg_free(line_buf);
1832 error05:
1833         if (path_buf.s) pkg_free(path_buf.s);
1834 error00:
1835         *returned_len=0;
1836         return 0;
1837 }
1838
1839
1840
1841 char * build_res_buf_from_sip_res( struct sip_msg* msg,
1842                                 unsigned int *returned_len)
1843 {
1844         unsigned int new_len, via_len, body_delta;
1845         char* new_buf;
1846         unsigned offset, s_offset, via_offset;
1847         char* buf;
1848         unsigned int len;
1849
1850         buf=msg->buf;
1851         len=msg->len;
1852         new_buf=0;
1853         /* we must remove the first via */
1854         if (msg->via1->next) {
1855                 via_len=msg->via1->bsize;
1856                 via_offset=msg->h_via1->body.s-buf;
1857         } else {
1858                 via_len=msg->h_via1->len;
1859                 via_offset=msg->h_via1->name.s-buf;
1860         }
1861
1862              /* Calculate message body difference and adjust
1863               * Content-Length
1864               */
1865         body_delta = lumps_len(msg, msg->body_lumps, 0);
1866         if (adjust_clen(msg, body_delta, (msg->via2? msg->via2->proto:PROTO_UDP))
1867                         < 0) {
1868                 LOG(L_ERR, "ERROR: build_req_buf_from_sip_req: Error while adjusting"
1869                                 " Content-Length\n");
1870                 goto error;
1871         }
1872
1873         /* remove the first via*/
1874         if (del_lump( msg, via_offset, via_len, HDR_VIA_T)==0){
1875                 LOG(L_ERR, "build_res_buf_from_sip_res: error trying to remove first"
1876                                         "via\n");
1877                 goto error;
1878         }
1879
1880         new_len=len+body_delta+lumps_len(msg, msg->add_rm, 0); /*FIXME: we don't
1881                                                                                                                 know the send sock */
1882
1883         DBG(" old size: %d, new size: %d\n", len, new_len);
1884         new_buf=(char*)pkg_malloc(new_len+1); /* +1 is for debugging
1885                                                                                          (\0 to print it )*/
1886         if (new_buf==0){
1887                 LOG(L_ERR, "ERROR: build_res_buf_from_sip_res: out of mem\n");
1888                 goto error;
1889         }
1890         new_buf[new_len]=0; /* debug: print the message */
1891         offset=s_offset=0;
1892         /*FIXME: no send sock*/
1893         process_lumps(msg, msg->add_rm, new_buf, &offset, &s_offset, 0);/*FIXME:*/
1894         process_lumps(msg, msg->body_lumps, new_buf, &offset, &s_offset, 0);
1895         /* copy the rest of the message */
1896         memcpy(new_buf+offset,
1897                 buf+s_offset,
1898                 len-s_offset);
1899          /* send it! */
1900         DBG("build_res_from_sip_res: copied size: orig:%d, new: %d, rest: %d"
1901                         " msg=\n%s\n", s_offset, offset, len-s_offset, new_buf);
1902
1903         *returned_len=new_len;
1904         return new_buf;
1905 error:
1906         *returned_len=0;
1907         return 0;
1908 }
1909
1910
1911 char * build_res_buf_from_sip_req( unsigned int code, char *text ,str *new_tag,
1912                 struct sip_msg* msg, unsigned int *returned_len, struct bookmark *bmark)
1913 {
1914         char              *buf, *p;
1915         unsigned int      len,foo;
1916         struct hdr_field  *hdr;
1917         struct lump_rpl   *lump;
1918         struct lump_rpl   *body;
1919         int               i;
1920         char*             received_buf;
1921         unsigned int      received_len;
1922         char*             rport_buf;
1923         unsigned int      rport_len;
1924         char*             warning_buf;
1925         unsigned int      warning_len;
1926         char*             content_len_buf;
1927         unsigned int      content_len_len;
1928         unsigned int      text_len;
1929         char *after_body;
1930         str  to_tag;
1931         char *totags;
1932
1933         body = 0;
1934         buf=0;
1935         received_buf=rport_buf=warning_buf=content_len_buf=0;
1936         received_len=rport_len=warning_len=content_len_len=0;
1937
1938         text_len=strlen(text);
1939
1940         to_tag.s=0;  /* fixes gcc 4.0 warning */
1941         to_tag.len=0;
1942
1943         /* force parsing all headers -- we want to return all
1944         Via's in the reply and they may be scattered down to the
1945         end of header (non-block Vias are a really poor property
1946         of SIP :( ) */
1947         if (parse_headers( msg, HDR_EOH_F, 0 )==-1) {
1948                 LOG(L_ERR, "ERROR: build_res_buf_from_sip_req: "
1949                         "alas, parse_headers failed\n");
1950                 goto error00;
1951         }
1952
1953         /*computes the length of the new response buffer*/
1954         len = 0;
1955
1956         /* check if received needs to be added */
1957         if (received_test(msg)) {
1958                 if ((received_buf=received_builder(msg,&received_len))==0) {
1959                         LOG(L_ERR, "ERROR: build_res_buf_from_sip_req: "
1960                                 "alas, received_builder failed\n");
1961                         goto error00;
1962                 }
1963         }
1964         /* check if rport needs to be updated */
1965         if ( ((msg->msg_flags|global_req_flags)&FL_FORCE_RPORT)||
1966                 (msg->via1->rport /*&& msg->via1->rport->value.s==0*/)){
1967                 if ((rport_buf=rport_builder(msg, &rport_len))==0){
1968                         LOG(L_ERR, "ERROR: build_res_buf_from_sip_req:"
1969                                                         " rport_builder failed\n");
1970                         goto error01; /* free everything */
1971                 }
1972                 if (msg->via1->rport)
1973                         len -= msg->via1->rport->size+1; /* include ';' */
1974         }
1975
1976         /* first line */
1977         len += msg->first_line.u.request.version.len + 1/*space*/ + 3/*code*/ + 1/*space*/ +
1978                 text_len + CRLF_LEN/*new line*/;
1979         /*headers that will be copied (TO, FROM, CSEQ,CALLID,VIA)*/
1980         for ( hdr=msg->headers ; hdr ; hdr=hdr->next ) {
1981                 switch (hdr->type) {
1982                         case HDR_TO_T:
1983                                 if (new_tag && new_tag->len) {
1984                                         to_tag=get_to(msg)->tag_value;
1985                                         if (to_tag.len )
1986                                                 len+=new_tag->len-to_tag.len;
1987                                         else
1988                                                 len+=new_tag->len+TOTAG_TOKEN_LEN/*";tag="*/;
1989                                 }
1990                                 len += hdr->len;
1991                                 break;
1992                         case HDR_VIA_T:
1993                                 /* we always add CRLF to via*/
1994                                 len+=(hdr->body.s+hdr->body.len)-hdr->name.s+CRLF_LEN;
1995                                 if (hdr==msg->h_via1) len += received_len+rport_len;
1996                                 break;
1997                         case HDR_RECORDROUTE_T:
1998                                 /* RR only for 1xx and 2xx replies */
1999                                 if (code<180 || code>=300)
2000                                         break;
2001                         case HDR_FROM_T:
2002                         case HDR_CALLID_T:
2003                         case HDR_CSEQ_T:
2004                                 /* we keep the original termination for these headers*/
2005                                 len += hdr->len;
2006                                 break;
2007                         default:
2008                                 /* do nothing, we are interested only in the above headers */
2009                                 ;
2010                 }
2011         }
2012         /* lumps length */
2013         for(lump=msg->reply_lump;lump;lump=lump->next) {
2014                 len += lump->text.len;
2015                 if (lump->flags&LUMP_RPL_BODY)
2016                         body = lump;
2017         }
2018         /* server header */
2019         if (server_signature)
2020                 len += server_hdr.len + CRLF_LEN;
2021         /* warning hdr */
2022         if (sip_warning) {
2023                 warning_buf = warning_builder(msg,&warning_len);
2024                 if (warning_buf) len += warning_len + CRLF_LEN;
2025                 else LOG(L_WARN, "WARNING: warning skipped -- too big\n");
2026         }
2027         /* content length hdr */
2028         if (body) {
2029                 content_len_buf = int2str(body->text.len, (int*)&content_len_len);
2030                 len += CONTENT_LENGTH_LEN + content_len_len + CRLF_LEN;
2031         } else {
2032                 len += CONTENT_LENGTH_LEN + 1/*0*/ + CRLF_LEN;
2033         }
2034         /* end of message */
2035         len += CRLF_LEN; /*new line*/
2036
2037         /*allocating mem*/
2038         buf = (char*) pkg_malloc( len+1 );
2039         if (!buf)
2040         {
2041                 LOG(L_ERR, "ERROR: build_res_buf_from_sip_req: out of memory "
2042                         " ; needs %d\n",len);
2043                 goto error01;
2044         }
2045
2046         /* filling the buffer*/
2047         p=buf;
2048         /* first line */
2049         memcpy( p , msg->first_line.u.request.version.s , 
2050                 msg->first_line.u.request.version.len);
2051         p += msg->first_line.u.request.version.len;
2052         *(p++) = ' ' ;
2053         /*code*/
2054         for ( i=2 , foo = code  ;  i>=0  ;  i-- , foo=foo/10 )
2055                 *(p+i) = '0' + foo - ( foo/10 )*10;
2056         p += 3;
2057         *(p++) = ' ' ;
2058         memcpy( p , text , text_len );
2059         p += text_len;
2060         memcpy( p, CRLF, CRLF_LEN );
2061         p+=CRLF_LEN;
2062         /* headers*/
2063         for ( hdr=msg->headers ; hdr ; hdr=hdr->next ) {
2064                 switch (hdr->type)
2065                 {
2066                         case HDR_VIA_T:
2067                                 if (hdr==msg->h_via1){
2068                                         if (rport_buf){
2069                                                 if (msg->via1->rport){ /* delete the old one */
2070                                                         /* copy until rport */
2071                                                         append_str_trans( p, hdr->name.s ,
2072                                                                 msg->via1->rport->start-hdr->name.s-1,msg);
2073                                                         /* copy new rport */
2074                                                         append_str(p, rport_buf, rport_len);
2075                                                         /* copy the rest of the via */
2076                                                         append_str_trans(p, msg->via1->rport->start+
2077                                                                                                 msg->via1->rport->size,
2078                                                                                                 hdr->body.s+hdr->body.len-
2079                                                                                                 msg->via1->rport->start-
2080                                                                                                 msg->via1->rport->size, msg);
2081                                                 }else{ /* just append the new one */
2082                                                         /* normal whole via copy */
2083                                                         append_str_trans( p, hdr->name.s ,
2084                                                                 (hdr->body.s+hdr->body.len)-hdr->name.s, msg);
2085                                                         append_str(p, rport_buf, rport_len);
2086                                                 }
2087                                         }else{
2088                                                 /* normal whole via copy */
2089                                                 append_str_trans( p, hdr->name.s ,
2090                                                                 (hdr->body.s+hdr->body.len)-hdr->name.s, msg);
2091                                         }
2092                                         if (received_buf)
2093                                                 append_str( p, received_buf, received_len);
2094                                 }else{
2095                                         /* normal whole via copy */
2096                                         append_str_trans( p, hdr->name.s,
2097                                                         (hdr->body.s+hdr->body.len)-hdr->name.s, msg);
2098                                 }
2099                                 append_str( p, CRLF,CRLF_LEN);
2100                                 break;
2101                         case HDR_RECORDROUTE_T:
2102                                 /* RR only for 1xx and 2xx replies */
2103                                 if (code<180 || code>=300) break;
2104                                 append_str(p, hdr->name.s, hdr->len);
2105                                 break;
2106                         case HDR_TO_T:
2107                                 if (new_tag && new_tag->len){
2108                                         if (to_tag.s ) { /* replacement */
2109                                                 /* before to-tag */
2110                                                 append_str( p, hdr->name.s, to_tag.s-hdr->name.s);
2111                                                 /* to tag replacement */
2112                                                 bmark->to_tag_val.s=p;
2113                                                 bmark->to_tag_val.len=new_tag->len;
2114                                                 append_str( p, new_tag->s,new_tag->len);
2115                                                 /* the rest after to-tag */
2116                                                 append_str( p, to_tag.s+to_tag.len,
2117                                                         hdr->name.s+hdr->len-(to_tag.s+to_tag.len));
2118                                         }else{ /* adding a new to-tag */
2119                                                 after_body=hdr->body.s+hdr->body.len;
2120                                                 append_str( p, hdr->name.s, after_body-hdr->name.s);
2121                                                 append_str(p, TOTAG_TOKEN, TOTAG_TOKEN_LEN);
2122                                                 bmark->to_tag_val.s=p;
2123                                                 bmark->to_tag_val.len=new_tag->len;
2124                                                 append_str( p, new_tag->s,new_tag->len);
2125                                                 append_str( p, after_body,
2126                                                                                 hdr->name.s+hdr->len-after_body);
2127                                         }
2128                                         break;
2129                                 } /* no new to-tag -- proceed to 1:1 copying  */
2130                                 totags=((struct to_body*)(hdr->parsed))->tag_value.s;
2131                                 if (totags) {
2132                                         bmark->to_tag_val.s=p+(totags-hdr->name.s);
2133                                         bmark->to_tag_val.len=
2134                                                         ((struct to_body*)(hdr->parsed))->tag_value.len;
2135                                 }
2136                                 else {
2137                                         bmark->to_tag_val.len = 0;
2138                                         bmark->to_tag_val.s = p+(hdr->body.s+hdr->body.len-hdr->name.s);
2139                                 }
2140                                 /* no break */
2141                         case HDR_FROM_T:
2142                         case HDR_CALLID_T:
2143                         case HDR_CSEQ_T:
2144                                         append_str(p, hdr->name.s, hdr->len);
2145                                         break;
2146                         default:
2147                                 /* do nothing, we are interested only in the above headers */
2148                                 ;
2149                 } /* end switch */
2150         } /* end for */
2151         /* lumps */
2152         for(lump=msg->reply_lump;lump;lump=lump->next)
2153                 if (lump->flags&LUMP_RPL_HDR){
2154                         memcpy(p,lump->text.s,lump->text.len);
2155                         p += lump->text.len;
2156                 }
2157         /* server header */
2158         if (server_signature) {
2159                 memcpy( p, server_hdr.s, server_hdr.len );
2160                 p+=server_hdr.len;
2161                 memcpy( p, CRLF, CRLF_LEN );
2162                 p+=CRLF_LEN;
2163         }
2164         /* content_length hdr */
2165         if (content_len_len) {
2166                 append_str( p, CONTENT_LENGTH, CONTENT_LENGTH_LEN);
2167                 append_str( p, content_len_buf, content_len_len );
2168                 append_str( p, CRLF, CRLF_LEN );
2169         } else {
2170                 append_str( p, CONTENT_LENGTH"0"CRLF,CONTENT_LENGTH_LEN+1+CRLF_LEN);
2171         }
2172         /* warning header */
2173         if (warning_buf) {
2174                 memcpy( p, warning_buf, warning_len);
2175                 p+=warning_len;
2176                 memcpy( p, CRLF, CRLF_LEN);
2177                 p+=CRLF_LEN;
2178         }
2179         /*end of message*/
2180         memcpy( p, CRLF, CRLF_LEN );
2181         p+=CRLF_LEN;
2182         /* body */
2183         if (body) {
2184                 memcpy ( p, body->text.s, body->text.len );
2185                 p+=body->text.len;
2186         }
2187
2188         if (len!=p-buf)
2189                 LOG(L_CRIT,"BUG:build_res_from_sip_req: diff len=%d p-buf=%d\n",
2190                                         len, (int)(p-buf));
2191
2192         *(p) = 0;
2193         *returned_len = len;
2194         /* in req2reply, received_buf is not introduced to lumps and
2195            needs to be deleted here
2196         */
2197         if (received_buf) pkg_free(received_buf);
2198         if (rport_buf) pkg_free(rport_buf);
2199         return buf;
2200
2201 error01:
2202         if (received_buf) pkg_free(received_buf);
2203         if (rport_buf) pkg_free(rport_buf);
2204 error00:
2205         *returned_len=0;
2206         return 0;
2207 }
2208
2209
2210
2211 /* return number of chars printed or 0 if space exceeded;
2212    assumes buffer size of at least MAX_BRANCH_PARAM_LEN
2213  */
2214 int branch_builder( unsigned int hash_index,
2215         /* only either parameter useful */
2216         unsigned int label, char * char_v,
2217         int branch,
2218         char *branch_str, int *len )
2219 {
2220
2221         char *begin;
2222         int size;
2223
2224         /* hash id provided ... start with it */
2225         size=MAX_BRANCH_PARAM_LEN;
2226         begin=branch_str;
2227         *len=0;
2228
2229         memcpy(begin, MCOOKIE, MCOOKIE_LEN );
2230         size-=MCOOKIE_LEN;begin+=MCOOKIE_LEN;
2231
2232         if (int2reverse_hex( &begin, &size, hash_index)==-1)
2233                 return 0;
2234
2235         if (size) {
2236                 *begin=BRANCH_SEPARATOR;
2237                 begin++; size--;
2238         } else return 0;
2239
2240         /* string with request's characteristic value ... use it ... */
2241         if (char_v) {
2242                 if (memcpy(begin,char_v,MD5_LEN)) {
2243                         begin+=MD5_LEN; size-=MD5_LEN;
2244                 } else return 0;
2245         } else { /* ... use the "label" value otherwise */
2246                 if (int2reverse_hex( &begin, &size, label )==-1)
2247                         return 0;
2248         }
2249
2250         if (size) {
2251                 *begin=BRANCH_SEPARATOR;
2252                 begin++; size--;
2253         } else return 0;
2254
2255         if (int2reverse_hex( &begin, &size, branch)==-1)
2256                 return 0;
2257
2258         *len=MAX_BRANCH_PARAM_LEN-size;
2259         return size;
2260
2261 }
2262
2263
2264
2265 /* uses only the send_info->send_socket, send_info->proto and 
2266  * send_info->comp (so that a send_info used for sending can be passed
2267  * to this function w/o changes and the correct via will be built) */
2268 char* via_builder( unsigned int *len,
2269         struct dest_info* send_info /* where to send the reply */,
2270         str* branch, str* extra_params, struct hostport* hp)
2271 {
2272         unsigned int  via_len, extra_len;
2273         char               *line_buf;
2274         int max_len;
2275         int via_prefix_len;
2276         str* address_str; /* address displayed in via */
2277         str* port_str; /* port no displayed in via */
2278         struct socket_info* send_sock;
2279         int comp_len, comp_name_len;
2280         char* comp_name;
2281
2282         send_sock=send_info->send_sock;
2283         /* use pre-set address in via or the outbound socket one */
2284         if ( hp && hp->host->len)
2285                 address_str=hp->host;
2286         else
2287                 address_str=&(send_sock->address_str);
2288         if (hp && hp->port->len)
2289                 port_str=hp->port;
2290         else
2291                 port_str=&(send_sock->port_no_str);
2292         
2293         comp_len=comp_name_len=0;
2294         comp_name=0;
2295 #ifdef USE_COMP
2296         switch(send_info->comp){
2297                 case COMP_NONE:
2298                         break;
2299                 case COMP_SIGCOMP:
2300                         comp_len=COMP_PARAM_LEN;
2301                         comp_name_len=SIGCOMP_NAME_LEN;
2302                         comp_name=SIGCOMP_NAME;
2303                         break;
2304                 case COMP_SERGZ:
2305                         comp_len=COMP_PARAM_LEN;
2306                         comp_name_len=SERGZ_NAME_LEN;
2307                         comp_name=SERGZ_NAME;
2308                         break;
2309                 default:
2310                         LOG(L_CRIT, "BUG: via_builder: unknown comp %d\n",
2311                                         send_info->comp);
2312                         /* continue, we'll just ignore comp */
2313         }
2314 #endif /* USE_COMP */
2315                         
2316         via_prefix_len=MY_VIA_LEN+(send_info->proto==PROTO_SCTP);
2317         max_len=via_prefix_len +address_str->len /* space in MY_VIA */
2318                 +2 /* just in case it is a v6 address ... [ ] */
2319                 +1 /*':'*/+port_str->len
2320                 +(branch?(MY_BRANCH_LEN+branch->len):0)
2321                 +(extra_params?extra_params->len:0)
2322                 +comp_len+comp_name_len
2323                 +CRLF_LEN+1;
2324         line_buf=pkg_malloc( max_len );
2325         if (line_buf==0){
2326                 ser_error=E_OUT_OF_MEM;
2327                 LOG(L_ERR, "ERROR: via_builder: out of memory\n");
2328                 return 0;
2329         }
2330
2331         extra_len=0;
2332
2333         via_len=via_prefix_len+address_str->len; /*space included in MY_VIA*/
2334
2335         memcpy(line_buf, MY_VIA, MY_VIA_LEN);
2336         if (send_info->proto==PROTO_UDP){
2337                 /* do nothing */
2338         }else if (send_info->proto==PROTO_TCP){
2339                 memcpy(line_buf+MY_VIA_LEN-4, "TCP ", 4);
2340         }else if (send_info->proto==PROTO_TLS){
2341                 memcpy(line_buf+MY_VIA_LEN-4, "TLS ", 4);
2342         }else if (send_info->proto==PROTO_SCTP){
2343                 memcpy(line_buf+MY_VIA_LEN-4, "SCTP ", 5);
2344         }else{
2345                 LOG(L_CRIT, "BUG: via_builder: unknown proto %d\n", send_info->proto);
2346                 return 0;
2347         }
2348 #       ifdef USE_IPV6
2349         /* add [] only if ipv6 and outbound socket address is used;
2350          * if using pre-set no check is made */
2351         if ((send_sock->address.af==AF_INET6) &&
2352                 (address_str==&(send_sock->address_str))) {
2353                 line_buf[via_prefix_len]='[';
2354                 line_buf[via_prefix_len+1+address_str->len]=']';
2355                 extra_len=1;
2356                 via_len+=2; /* [ ]*/
2357         }
2358 #       endif
2359         memcpy(line_buf+via_prefix_len+extra_len, address_str->s,
2360                                 address_str->len);
2361         if ((send_sock->port_no!=SIP_PORT) ||
2362                                 (port_str!=&send_sock->port_no_str)){
2363                 line_buf[via_len]=':'; via_len++;
2364                 memcpy(line_buf+via_len, port_str->s, port_str->len);
2365                 via_len+=port_str->len;
2366         }
2367
2368         /* branch parameter */
2369         if (branch){
2370                 memcpy(line_buf+via_len, MY_BRANCH, MY_BRANCH_LEN );
2371                 via_len+=MY_BRANCH_LEN;
2372                 memcpy(line_buf+via_len, branch->s, branch->len );
2373                 via_len+=branch->len;
2374         }
2375         /* extra params  */
2376         if (extra_params){
2377                 memcpy(line_buf+via_len, extra_params->s, extra_params->len);
2378                 via_len+=extra_params->len;
2379         }
2380 #ifdef USE_COMP
2381         /* comp */
2382         if (comp_len){
2383                 memcpy(line_buf+via_len, COMP_PARAM, COMP_PARAM_LEN);
2384                 via_len+=COMP_PARAM_LEN;
2385                 memcpy(line_buf+via_len, comp_name, comp_name_len);
2386                 via_len+=comp_name_len;
2387         }
2388 #endif
2389
2390         memcpy(line_buf+via_len, CRLF, CRLF_LEN);
2391         via_len+=CRLF_LEN;
2392         line_buf[via_len]=0; /* null terminate the string*/
2393
2394         *len = via_len;
2395         return line_buf;
2396 }
2397
2398 /* creates a via header honoring the protocol of the incomming socket
2399  * msg is an optional parameter */
2400 char* create_via_hf( unsigned int *len,
2401         struct sip_msg *msg,
2402         struct dest_info* send_info /* where to send the reply */,
2403         str* branch)
2404 {
2405         char* via;
2406         str extra_params;
2407         struct hostport hp;
2408 #if defined USE_TCP || defined USE_SCTP
2409         char* id_buf;
2410         unsigned int id_len;
2411
2412
2413         id_buf=0;
2414         id_len=0;
2415 #endif
2416         extra_params.len=0;
2417         extra_params.s=0;
2418
2419
2420 #if defined USE_TCP || defined USE_SCTP
2421         /* add id if tcp */
2422         if (msg && (
2423 #ifdef USE_TCP
2424                 (msg->rcv.proto==PROTO_TCP)
2425 #ifdef USE_TLS
2426                         || (msg->rcv.proto==PROTO_TLS)
2427 #endif
2428 #ifdef USE_SCTP
2429                         ||
2430 #endif /* USE_SCTP */
2431 #endif /* USE_TCP */
2432 #ifdef USE_SCTP
2433                         (msg->rcv.proto==PROTO_SCTP)
2434 #endif /* USE_SCTP */
2435                         )){
2436                 if  ((id_buf=id_builder(msg, &id_len))==0){
2437                         LOG(L_ERR, "ERROR: create_via_hf:"
2438                                                         " id_builder failed\n");
2439                         return 0; /* we don't need to free anything,
2440                                          nothing alloc'ed yet*/
2441                 }
2442                 DBG("create_via_hf: id added: <%.*s>, rcv proto=%d\n",
2443                                 (int)id_len, id_buf, msg->rcv.proto);
2444                 extra_params.s=id_buf;
2445                 extra_params.len=id_len;
2446         }
2447 #endif /* USE_TCP || USE_SCTP */
2448
2449         /* test and add rport parameter to local via - rfc3581 */
2450         if(msg->msg_flags&FL_ADD_LOCAL_RPORT) {
2451                 /* params so far + ';rport' + '\0' */
2452                 via = (char*)pkg_malloc(extra_params.len+RPORT_LEN);
2453                 if(via==0) {
2454                         LM_ERR("building local rport via param failed\n");
2455                         if (extra_params.s) pkg_free(extra_params.s);
2456                         return 0;
2457                 }
2458                 if(extra_params.len!=0) {
2459                         memcpy(via, extra_params.s, extra_params.len);
2460                         pkg_free(extra_params.s);
2461                 }
2462                 memcpy(via + extra_params.len, RPORT, RPORT_LEN-1);
2463                 extra_params.s = via;
2464                 extra_params.len += RPORT_LEN-1;
2465                 extra_params.s[extra_params.len]='\0';
2466         }
2467
2468         set_hostport(&hp, msg);
2469         via = via_builder( len, send_info, branch,
2470                                                         extra_params.len?&extra_params:0, &hp);
2471
2472         /* we do not need extra_params any more, already in the new via header */
2473         if (extra_params.s) pkg_free(extra_params.s);
2474         return via;
2475 }
2476
2477 /* builds a char* buffer from message headers without body
2478  * first line is excluded in case of skip_first_line=1
2479  * error is set -1 if the memory allocation failes
2480  */
2481 char * build_only_headers( struct sip_msg* msg, int skip_first_line,
2482                                 unsigned int *returned_len,
2483                                 int *error,
2484                                 struct dest_info* send_info)
2485 {
2486         char            *buf, *new_buf;
2487         unsigned int    offset, s_offset, len, new_len;
2488
2489         *error = 0;
2490         buf = msg->buf;
2491         if (skip_first_line)
2492                 s_offset = msg->headers->name.s - buf;
2493         else
2494                 s_offset = 0;
2495
2496         /* original length without body, and without final \r\n */
2497         len = msg->unparsed - buf;
2498         /* new msg length */
2499         new_len =       len - /* original length  */
2500                         s_offset + /* skipped first line */
2501                         lumps_len(msg, msg->add_rm, send_info); /* lumps */
2502
2503         if (new_len == 0) {
2504                 *returned_len = 0;
2505                 return 0;
2506         }
2507
2508         new_buf = (char *)pkg_malloc(new_len+1);
2509         if (!new_buf) {
2510                 LOG(L_ERR, "ERROR: build_only_headers: Not enough memory\n");
2511                 *error = -1;
2512                 return 0;
2513         }
2514         new_buf[0] = 0;
2515         offset = 0;
2516
2517         /* copy message lumps */
2518         process_lumps(msg, msg->add_rm, new_buf, &offset, &s_offset, send_info);
2519         /* copy the rest of the message without body */
2520         if (len > s_offset) {
2521                 memcpy(new_buf+offset, buf+s_offset, len-s_offset);
2522                 offset += (len-s_offset);
2523         }
2524         new_buf[offset] = 0;
2525
2526         *returned_len = offset;
2527         return new_buf;
2528 }
2529
2530 /* builds a char* buffer from message body
2531  * error is set -1 if the memory allocation failes
2532  */
2533 char * build_body( struct sip_msg* msg,
2534                         unsigned int *returned_len,
2535                         int *error,
2536                         struct dest_info* send_info)
2537 {
2538         char            *buf, *new_buf, *body;
2539         unsigned int    offset, s_offset, len, new_len;
2540
2541         *error = 0;
2542         body = get_body(msg);
2543
2544         if (!body || (body[0] == 0)) {
2545                 *returned_len = 0;
2546                 return 0;
2547         }
2548         buf = msg->buf;
2549         s_offset = body - buf;
2550
2551         /* original length of msg with body */
2552         len = msg->len;
2553         /* new body length */
2554         new_len =       len - /* original length  */
2555                         s_offset + /* msg without body */
2556                         lumps_len(msg, msg->body_lumps, send_info); /* lumps */
2557
2558         new_buf = (char *)pkg_malloc(new_len+1);
2559         if (!new_buf) {
2560                 LOG(L_ERR, "ERROR: build_body: Not enough memory\n");
2561                 *error = -1;
2562                 return 0;
2563         }
2564         new_buf[0] = 0;
2565         offset = 0;
2566
2567         /* copy body lumps */
2568         process_lumps(msg, msg->body_lumps, new_buf, &offset, &s_offset, send_info);
2569         /* copy the rest of the message without body */
2570         if (len > s_offset) {
2571                 memcpy(new_buf+offset, buf+s_offset, len-s_offset);
2572                 offset += (len-s_offset);
2573         }
2574         new_buf[offset] = 0;
2575
2576         *returned_len = offset;
2577         return new_buf;
2578 }
2579
2580 /* builds a char* buffer from SIP message including body
2581  * The function adjusts the Content-Length HF according
2582  * to body lumps in case of touch_clen=1.
2583  */
2584 char * build_all( struct sip_msg* msg, int touch_clen,
2585                         unsigned int *returned_len,
2586                         int *error,
2587                         struct dest_info* send_info)
2588 {
2589         char            *buf, *new_buf;
2590         unsigned int    offset, s_offset, len, new_len;
2591         unsigned int    body_delta;
2592
2593         *error = 0;
2594         /* Calculate message body difference */
2595         body_delta = lumps_len(msg, msg->body_lumps, send_info);
2596         if (touch_clen) {
2597                 /* adjust Content-Length */
2598                 if (adjust_clen(msg, body_delta, send_info->proto) < 0) {
2599                         LOG(L_ERR, "ERROR: build_all: Error while adjusting"
2600                                         " Content-Length\n");
2601                         *error = -1;
2602                         return 0;
2603                 }
2604         }
2605
2606         buf = msg->buf;
2607         /* original msg length */
2608         len = msg->len;
2609         /* new msg length */
2610         new_len =       len + /* original length  */
2611                         lumps_len(msg, msg->add_rm, send_info) + /* hdr lumps */
2612                         body_delta; /* body lumps */
2613
2614         if (new_len == 0) {
2615                 returned_len = 0;
2616                 return 0;
2617         }
2618
2619         new_buf = (char *)pkg_malloc(new_len+1);
2620         if (!new_buf) {
2621                 LOG(L_ERR, "ERROR: build_all: Not enough memory\n");
2622                 *error = -1;
2623                 return 0;
2624         }
2625         new_buf[0] = 0;
2626         offset = s_offset = 0;
2627
2628         /* copy message lumps */
2629         process_lumps(msg, msg->add_rm, new_buf, &offset, &s_offset, send_info);
2630         /* copy body lumps */
2631         process_lumps(msg, msg->body_lumps, new_buf, &offset, &s_offset, send_info);
2632         /* copy the rest of the message */
2633         memcpy(new_buf+offset, buf+s_offset, len-s_offset);
2634         offset += (len-s_offset);
2635         new_buf[offset] = 0;
2636
2637         *returned_len = offset;
2638         return new_buf; 
2639 }
2640
2641
2642
2643 /**
2644  * parse buf in msg and fill several fields
2645  */
2646 int build_sip_msg_from_buf(struct sip_msg *msg, char *buf, int len,
2647                 unsigned int id)
2648 {
2649         if(msg==0 || buf==0)
2650                 return -1;
2651
2652         memset(msg, 0, sizeof(sip_msg_t));
2653         msg->id = id;
2654         msg->buf = buf;
2655         msg->len = len;
2656         if (parse_msg(buf, len, msg)!=0) {
2657                 LM_ERR("parsing failed");
2658                 return -1;
2659         }
2660         msg->set_global_address=default_global_address;
2661         msg->set_global_port=default_global_port;
2662         return 0;
2663 }
2664