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