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