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