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