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