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