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