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