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