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