parser changed to make body to point to body (w/o LWS), have a len
[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  *
40  */
41
42
43
44 #include <sys/types.h>
45 #include <sys/socket.h>
46 #include <netdb.h>
47 #include <string.h>
48 #include <stdio.h>
49 #include <stdlib.h>
50
51 #include "comp_defs.h"
52 #include "msg_translator.h"
53 #include "globals.h"
54 #include "error.h"
55 #include "mem/mem.h"
56 #include "dprint.h"
57 #include "config.h"
58 #include "md5utils.h"
59 #include "data_lump_rpl.h"
60 #include "ip_addr.h"
61 #include "resolve.h"
62 #include "ut.h"
63 #include "pt.h"
64
65
66 #define append_str(_dest,_src,_len) \
67         do{\
68                 memcpy( (_dest) , (_src) , (_len) );\
69                 (_dest) += (_len) ;\
70         }while(0);
71
72 #define append_str_trans(_dest,_src,_len,_msg) \
73         append_str( (_dest), (_msg)->orig+((_src)-(_msg)->buf) , (_len) );
74
75 extern char version[];
76 extern int version_len;
77
78
79
80 /* checks if ip is in host(name) and ?host(ip)=name?
81  * ip must be in network byte order!
82  *  resolver = DO_DNS | DO_REV_DNS; if 0 no dns check is made
83  * return 0 if equal */
84 int check_address(struct ip_addr* ip, char *name, int resolver)
85 {
86         struct hostent* he;
87         int i;
88         char* s;
89
90         /* maybe we are lucky and name it's an ip */
91         s=ip_addr2a(ip);
92         if (s){
93                 DBG("check_address(%s, %s, %d)\n", s, name, resolver);
94         #ifdef USE_IPV6
95                 if ((ip->af==AF_INET6) && (strcasecmp(name, s)==0))
96                                 return 0;
97                 else
98         #endif
99                         if (strcmp(name, s)==0)
100                                 return 0;
101         }else{
102                 LOG(L_CRIT, "check_address: BUG: could not convert ip address\n");
103                 return -1;
104         }
105                 
106         if (resolver&DO_DNS){
107                 DBG("check_address: doing dns lookup\n");
108                 /* try all names ips */
109                 he=resolvehost(name);
110                 if (he && ip->af==he->h_addrtype){
111                         for(i=0;he && he->h_addr_list[i];i++){
112                                 if ( memcmp(&he->h_addr_list[i], ip->u.addr, ip->len)==0)
113                                         return 0;
114                         }
115                 }
116         }
117         if (resolver&DO_REV_DNS){
118                 DBG("check_address: doing rev. dns lookup\n");
119                 /* try reverse dns */
120                 he=rev_resolvehost(ip);
121                 if (he && (strcmp(he->h_name, name)==0))
122                         return 0;
123                 for (i=0; he && he->h_aliases[i];i++){
124                         if (strcmp(he->h_aliases[i],name)==0)
125                                 return 0;
126                 }
127         }
128         return -1;
129 }
130
131
132 static char * warning_builder( struct sip_msg *msg, unsigned int *returned_len)
133 {
134         static char buf[MAX_WARNING_LEN];
135         static unsigned int fix_len=0;
136         str *foo;
137         int print_len;
138
139         if (!fix_len)
140         {
141                 memcpy(buf+fix_len,WARNING, WARNING_LEN);
142                 fix_len +=WARNING_LEN;
143                 memcpy(buf+fix_len, bind_address->name.s,bind_address->name.len);
144                 fix_len += bind_address->name.len;
145                 //*(buf+fix_len++) = ':';
146                 memcpy(buf+fix_len,bind_address->port_no_str.s,
147                         bind_address->port_no_str.len);
148                 fix_len += bind_address->port_no_str.len;
149                 memcpy(buf+fix_len, WARNING_PHRASE,WARNING_PHRASE_LEN);
150                 fix_len += WARNING_PHRASE_LEN;
151         }
152
153         /*adding out_uri*/
154         if (msg->new_uri.s)
155                 foo=&(msg->new_uri);
156         else
157                 foo=&(msg->first_line.u.request.uri);
158         print_len=snprintf(buf+fix_len, MAX_WARNING_LEN-fix_len,
159                 "pid=%d req_src_ip=%s in_uri=%.*s out_uri=%.*s via_cnt%c=%d\"",
160                 my_pid(),
161                 ip_addr2a(&msg->rcv.src_ip),
162                 msg->first_line.u.request.uri.len, msg->first_line.u.request.uri.s,
163                 foo->len, foo->s, 
164                 msg->parsed_flag & HDR_EOH ? '=' : '>', /* should be = */
165                 via_cnt );
166
167         if (print_len==-1 || print_len>=MAX_WARNING_LEN-fix_len) {
168                 LOG(L_ERR, "ERROR: warning_builder: buffer size exceeded\n");
169                 *returned_len=0;
170                 return 0;
171         } else {
172                 *returned_len=fix_len+print_len;
173                 return buf;
174         }
175 }
176
177
178
179
180 char* received_builder(struct sip_msg *msg, unsigned int *received_len)
181 {
182         char *buf;
183         int  len;
184         struct ip_addr *source_ip;
185         char *tmp;
186         int  tmp_len;
187         int extra_len;
188
189         extra_len = 0;
190         source_ip=&msg->rcv.src_ip;
191
192         buf=pkg_malloc(sizeof(char)*MAX_RECEIVED_SIZE);
193         if (buf==0){
194                 ser_error=E_OUT_OF_MEM;
195                 LOG(L_ERR, "ERROR: received_builder: out of memory\n");
196                 return 0;
197         }
198         memcpy(buf, RECEIVED, RECEIVED_LEN);
199         if ( (tmp=ip_addr2a(source_ip))==0)
200                 return 0; /* error*/
201         tmp_len=strlen(tmp);
202         len=RECEIVED_LEN+tmp_len;
203         if(source_ip->af==AF_INET6){
204                 len+=2;
205                 buf[RECEIVED_LEN]='[';
206                 buf[RECEIVED_LEN+tmp_len+1]=']';
207                 extra_len=1;
208         }
209         
210         memcpy(buf+RECEIVED_LEN+extra_len, tmp, tmp_len);
211         buf[len+1]=0; /*null terminate it */
212
213         *received_len = len;
214         return buf;
215 }
216
217
218
219 char* rport_builder(struct sip_msg *msg, unsigned int *rport_len)
220 {
221         char* buf;
222         char* tmp;
223         int tmp_len;
224         int len;
225         
226         tmp_len=0;
227         tmp=int2str(ntohs(msg->rcv.src_port), &tmp_len);
228         len=RPORT_LEN+tmp_len; /* space for null term */
229         buf=pkg_malloc(sizeof(char)*(len+1));
230         if (buf==0){
231                 ser_error=E_OUT_OF_MEM;
232                 LOG(L_ERR, "ERROR: rport_builder: out of memory\n");
233                 return 0;
234         }
235         memcpy(buf, RPORT, RPORT_LEN);
236         memcpy(buf+RPORT_LEN, tmp, tmp_len);
237         buf[len+1]=0; /*null terminate it*/
238         
239         *rport_len=len;
240         return buf;
241 }
242
243
244
245 char* id_builder(struct sip_msg* msg, unsigned int *id_len)
246 {
247         char* buf;
248         int len, value_len;
249         char revhex[sizeof(int)*2];
250         char* p;
251         int size;
252         
253         size=sizeof(int)*2;
254         p=&revhex[0];
255         if (int2reverse_hex(&p, &size, msg->rcv.proto_reserved1)==-1){
256                 LOG(L_CRIT, "BUG: id_builder: not enough space for id\n");
257                 return 0;
258         }
259         value_len=p-&revhex[0];
260         len=ID_PARAM_LEN+value_len; /* place for ending \0 */
261         buf=pkg_malloc(sizeof(char)*(len+1));
262         if (buf==0){
263                 ser_error=E_OUT_OF_MEM;
264                 LOG(L_ERR, "ERROR: rport_builder: out of memory\n");
265                 return 0;
266         }
267         memcpy(buf, ID_PARAM, ID_PARAM_LEN);
268         memcpy(buf+ID_PARAM_LEN, revhex, value_len);
269         buf[len+1]=0; /* null terminate it */
270         *id_len=len;
271         return buf;
272 }
273
274
275
276 /* computes the "unpacked" len of a lump list,
277    code moved from build_req_from_req */
278 static inline int lumps_len(struct lump* l)
279 {
280         int s_offset;
281         int new_len;
282         struct lump* t;
283         struct lump* r;
284
285         s_offset=0;
286         new_len=0;
287         for(t=l;t;t=t->next){
288                 for(r=t->before;r;r=r->before){
289                         switch(r->op){
290                                 case LUMP_ADD:
291                                         new_len+=r->len;
292                                         break;
293                                 default:
294                                         /* only ADD allowed for before/after */
295                                         LOG(L_CRIT, "BUG: lumps_len: invalid op "
296                                                         "for data lump (%x)\n", r->op);
297                         }
298                 }
299                 switch(t->op){
300                         case LUMP_ADD:
301                                 new_len+=t->len;
302                                 break;
303                         case LUMP_DEL:
304                                 /* fix overlapping deleted zones */
305                                 if (t->u.offset < s_offset){
306                                         /* change len */
307                                         if (t->len>s_offset-t->u.offset)
308                                                         t->len-=s_offset-t->u.offset;
309                                         else t->len=0;
310                                         t->u.offset=s_offset;
311                                 }
312                                 s_offset=t->u.offset+t->len;
313                                 new_len-=t->len;
314                                 break;
315                         case LUMP_NOP:
316                                 /* fix offset if overlapping on a deleted zone */
317                                 if (t->u.offset < s_offset){
318                                         t->u.offset=s_offset;
319                                 }else
320                                         s_offset=t->u.offset;
321                                 /* do nothing */
322                                 break;
323                         default:
324                                 LOG(L_CRIT,"BUG:lumps_len: invalid"
325                                                         " op for data lump (%x)\n", r->op);
326                 }
327                 for (r=t->after;r;r=r->after){
328                         switch(r->op){
329                                 case LUMP_ADD:
330                                         new_len+=r->len;
331                                         break;
332                                 default:
333                                         /* only ADD allowed for before/after */
334                                         LOG(L_CRIT, "BUG:lumps_len: invalid"
335                                                                 " op for data lump (%x)\n", r->op);
336                         }
337                 }
338         }
339         return new_len;
340 }
341
342
343
344 /* another helper functions, adds/Removes the lump,
345         code moved form build_req_from_req  */
346
347 static inline void process_lumps(       struct lump* l, char* new_buf, 
348                                                                         unsigned int* new_buf_offs, char* orig,
349                                                                         unsigned int* orig_offs)
350 {
351         struct lump *t;
352         struct lump *r;
353         int size;
354         int offset;
355         int s_offset;
356         
357         offset=*new_buf_offs;
358         s_offset=*orig_offs;
359         
360         for (t=l;t;t=t->next){
361                 switch(t->op){
362                         case LUMP_ADD:
363                                 /* just add it here! */
364                                 /* process before  */
365                                 for(r=t->before;r;r=r->before){
366                                         switch (r->op){
367                                                 case LUMP_ADD:
368                                                         /*just add it here*/
369                                                         memcpy(new_buf+offset, r->u.value, r->len);
370                                                         offset+=r->len;
371                                                         break;
372                                                 default:
373                                                         /* only ADD allowed for before/after */
374                                                         LOG(L_CRIT, "BUG:process_lumps: "
375                                                                         "invalid op for data lump (%x)\n", r->op);
376                                         }
377                                 }
378                                 /* copy "main" part */
379                                 memcpy(new_buf+offset, t->u.value, t->len);
380                                 offset+=t->len;
381                                 /* process after */
382                                 for(r=t->after;r;r=r->after){
383                                         switch (r->op){
384                                                 case LUMP_ADD:
385                                                         /*just add it here*/
386                                                         memcpy(new_buf+offset, r->u.value, r->len);
387                                                         offset+=r->len;
388                                                         break;
389                                                 default:
390                                                         /* only ADD allowed for before/after */
391                                                         LOG(L_CRIT, "BUG:process_lumps: "
392                                                                         "invalid op for data lump (%x)\n", r->op);
393                                         }
394                                 }
395                                 break;
396                         case LUMP_NOP:
397                         case LUMP_DEL:
398                                 /* copy till offset */
399                                 if (s_offset>t->u.offset){
400                                         DBG("Warning: (%d) overlapped lumps offsets,"
401                                                 " ignoring(%x, %x)\n", t->op, s_offset,t->u.offset);
402                                         /* this should've been fixed above (when computing len) */
403                                         /* just ignore it*/
404                                         break;
405                                 }
406                                 size=t->u.offset-s_offset;
407                                 if (size){
408                                         memcpy(new_buf+offset, orig+s_offset,size);
409                                         offset+=size;
410                                         s_offset+=size;
411                                 }
412                                 /* process before  */
413                                 for(r=t->before;r;r=r->before){
414                                         switch (r->op){
415                                                 case LUMP_ADD:
416                                                         /*just add it here*/
417                                                         memcpy(new_buf+offset, r->u.value, r->len);
418                                                         offset+=r->len;
419                                                         break;
420                                                 default:
421                                                         /* only ADD allowed for before/after */
422                                                         LOG(L_CRIT, "BUG:process_lumps: "
423                                                                         "invalid op for data lump (%x)\n",r->op);
424                                         }
425                                 }
426                                 /* process main (del only) */
427                                 if (t->op==LUMP_DEL){
428                                         /* skip len bytes from orig msg */
429                                         s_offset+=t->len;
430                                 }
431                                 /* process after */
432                                 for(r=t->after;r;r=r->after){
433                                         switch (r->op){
434                                                 case LUMP_ADD:
435                                                         /*just add it here*/
436                                                         memcpy(new_buf+offset, r->u.value, r->len);
437                                                         offset+=r->len;
438                                                         break;
439                                                 default:
440                                                         /* only ADD allowed for before/after */
441                                                         LOG(L_CRIT, "BUG:process_lumps: "
442                                                                         "invalid op for data lump (%x)\n", r->op);
443                                         }
444                                 }
445                                 break;
446                         default:
447                                         LOG(L_CRIT, "BUG: process_lumps: "
448                                                         "unknown op (%x)\n", t->op);
449                 }
450         }
451         *new_buf_offs=offset;
452         *orig_offs=s_offset;
453 }
454
455
456
457 char * build_req_buf_from_sip_req( struct sip_msg* msg,
458                                                                 unsigned int *returned_len,
459                                                                 struct socket_info* send_sock, int proto)
460 {
461         unsigned int len, new_len, received_len, rport_len, uri_len, via_len;
462         char* line_buf;
463         char* received_buf;
464         char* rport_buf;
465         char* new_buf;
466         char* orig;
467         char* buf;
468         char  backup;
469         unsigned int offset, s_offset, size;
470         struct lump* anchor;
471         int r;
472         str branch;
473         str extra_params;
474         
475 #ifdef USE_TCP
476         char* id_buf;
477         int id_len;
478         
479         
480         id_buf=0;
481         id_len=0;
482 #endif
483         extra_params.len=0;
484         extra_params.s=0;
485         uri_len=0;
486         orig=msg->orig;
487         buf=msg->buf;
488         len=msg->len;
489         received_len=0;
490         rport_len=0;
491         new_buf=0;
492         received_buf=0;
493         rport_buf=0;
494         line_buf=0;
495
496         
497 #ifdef USE_TCP
498         /* add id if tcp */
499         if (msg->rcv.proto==PROTO_TCP){
500                 if  ((id_buf=id_builder(msg, &id_len))==0){
501                         LOG(L_ERR, "ERROR: build_req_buf_from_sip_req:"
502                                                         " id_builder failed\n");
503                         goto error01; /* free everything */
504                 }
505                 extra_params.s=id_buf;
506                 extra_params.len=id_len;
507         }
508 #endif
509         branch.s=msg->add_to_branch_s;
510         branch.len=msg->add_to_branch_len;
511         line_buf = via_builder( &via_len, send_sock, &branch,
512                                                         extra_params.len?&extra_params:0, proto);
513         if (!line_buf){
514                 LOG(L_ERR,"ERROR: build_req_buf_from_sip_req: no via received!\n");
515                 goto error00;
516         }
517         /* check if received needs to be added */
518         backup = msg->via1->host.s[msg->via1->host.len];
519         msg->via1->host.s[msg->via1->host.len] = 0;
520         r=check_address(&msg->rcv.src_ip, msg->via1->host.s, received_dns);
521         msg->via1->host.s[msg->via1->host.len] = backup;
522         if (r!=0){
523                 if ((received_buf=received_builder(msg,&received_len))==0){
524                         LOG(L_ERR, "ERROR: build_req_buf_from_sip_req:"
525                                                         " received_builder failed\n");
526                         goto error01;  /* free also line_buf */
527                 }
528         }
529         
530         /* check if rport needs to be updated */
531         if (msg->via1->rport && msg->via1->rport->value.s==0){
532                 if ((rport_buf=rport_builder(msg, &rport_len))==0){
533                         LOG(L_ERR, "ERROR: build_req_buf_from_sip_req:"
534                                                         " rport_builder failed\n");
535                         goto error01; /* free everything */
536                 }
537         }
538
539         /* add via header to the list */
540         /* try to add it before msg. 1st via */
541         /* add first via, as an anchor for second via*/
542         anchor=anchor_lump(&(msg->add_rm), msg->via1->hdr.s-buf, 0, HDR_VIA);
543         if (anchor==0) goto error01;
544         if (insert_new_lump_before(anchor, line_buf, via_len, HDR_VIA)==0)
545                 goto error01;
546         /* if received needs to be added, add anchor after host and add it */
547         if (received_len){
548                 if (msg->via1->params.s){
549                                 size= msg->via1->params.s-msg->via1->hdr.s-1; /*compensate
550                                                                                                                           for ';' */
551                 }else{
552                                 size= msg->via1->host.s-msg->via1->hdr.s+msg->via1->host.len;
553                                 if (msg->via1->port!=0){
554                                         /*size+=strlen(msg->via1->hdr.s+size+1)+1;*/
555                                         size += msg->via1->port_str.len + 1; /* +1 for ':'*/
556                                 }
557                         #ifdef USE_IPV6
558                                 if(send_sock->address.af==AF_INET6) size+=1; /* +1 for ']'*/
559                         #endif
560                 }
561                 anchor=anchor_lump(&(msg->add_rm),msg->via1->hdr.s-buf+size,0,
562                                 HDR_VIA);
563                 if (anchor==0) goto error02; /* free received_buf */
564                 if (insert_new_lump_after(anchor, received_buf, received_len, HDR_VIA)
565                                 ==0 ) goto error02; /* free received_buf */
566         }
567         /* if rport needs to be updated, delete it and add it's value */
568         if (rport_len){
569                 anchor=del_lump(&(msg->add_rm), msg->via1->rport->start-buf-1, /*';'*/
570                                                         msg->via1->rport->size+1 /* ; */, HDR_VIA);
571                 if (anchor==0) goto error03; /* free rport_buf*/
572                 if (insert_new_lump_after(anchor, rport_buf, rport_len, HDR_VIA)==0)
573                         goto error03; /* free rport_buf*/
574         }
575
576         /* compute new msg len and fix overlapping zones*/
577         new_len=len+lumps_len(msg->add_rm);
578
579         if (msg->new_uri.s){
580                 uri_len=msg->new_uri.len;
581                 new_len=new_len-msg->first_line.u.request.uri.len+uri_len;
582         }
583         new_buf=(char*)pkg_malloc(new_len+1);
584         if (new_buf==0){
585                 ser_error=E_OUT_OF_MEM;
586                 LOG(L_ERR, "ERROR: build_req_buf_from_sip_req: out of memory\n");
587                 goto error00;
588         }
589
590         offset=s_offset=0;
591         if (msg->new_uri.s){
592                 /* copy message up to uri */
593                 size=msg->first_line.u.request.uri.s-buf;
594                 memcpy(new_buf, orig, size);
595                 offset+=size;
596                 s_offset+=size;
597                 /* add our uri */
598                 memcpy(new_buf+offset, msg->new_uri.s, uri_len);
599                 offset+=uri_len;
600                 s_offset+=msg->first_line.u.request.uri.len; /* skip original uri */
601         }
602         new_buf[new_len]=0;
603         /* copy msg adding/removing lumps */
604         process_lumps(msg->add_rm, new_buf, &offset, orig, &s_offset);
605         /* copy the rest of the message */
606         memcpy(new_buf+offset, orig+s_offset, len-s_offset);
607         new_buf[new_len]=0;
608
609 #ifdef DBG_MSG_QA
610         if (new_buf[new_len-1]==0) {
611                 LOG(L_ERR, "ERROR: build_req_buf_from_sip_req: 0 in the end\n");
612                 abort();
613         }
614 #endif
615
616         *returned_len=new_len;
617         return new_buf;
618
619 error01:
620         pkg_free(line_buf);
621 #ifdef USE_TCP
622         if (id_buf) pkg_free(id_buf);
623 #endif
624 error02:
625         if (received_buf) pkg_free(received_buf);
626 error03:
627         if (rport_buf) pkg_free(rport_buf);
628 error00:
629         *returned_len=0;
630         return 0;
631 }
632
633
634 char * build_res_buf_from_sip_res( struct sip_msg* msg,
635                                 unsigned int *returned_len)
636 {
637         unsigned int new_len, via_len;
638         char* new_buf;
639         unsigned offset, s_offset, via_offset;
640         char* orig;
641         char* buf;
642         unsigned int len;
643
644         orig=msg->orig;
645         buf=msg->buf;
646         len=msg->len;
647         new_buf=0;
648         /* we must remove the first via */
649 #ifdef PRESERVE_ZT
650         via_len=msg->via1->bsize;
651         via_offset=msg->via1->hdr.s-buf;
652         DBG("via len: %d, initial via offset: %d\n", via_len, via_offset);
653         if (msg->via1->next){
654                 /* add hdr size*/
655                 via_offset+=msg->via1->hdr.len+1;
656             DBG(" adjusted via len: %d, initial offset: %d\n",
657                                 via_len, via_offset);
658         }else{
659                 /* add hdr size ("Via:")*/
660                 via_len+=msg->via1->hdr.len+1;
661         }
662 #else
663         if (msg->via1->next) {
664                 via_len=msg->via1->bsize;
665                 via_offset=msg->h_via1->body.s-buf;
666         } else {
667                 via_len=msg->h_via1->len;
668                 via_offset=msg->h_via1->name.s-buf;
669         }
670 #endif
671         /* remove the first via*/
672         if (del_lump( &(msg->repl_add_rm), via_offset, via_len, HDR_VIA)==0){
673                 LOG(L_ERR, "build_res_buf_from_sip_res: error trying to remove first"
674                                         "via\n");
675                 goto error;
676         }
677         new_len=len+lumps_len(msg->repl_add_rm);
678
679         DBG(" old size: %d, new size: %d\n", len, new_len);
680         new_buf=(char*)pkg_malloc(new_len+1); /* +1 is for debugging 
681                                                                                          (\0 to print it )*/
682         if (new_buf==0){
683                 LOG(L_ERR, "ERROR: build_res_buf_from_sip_res: out of mem\n");
684                 goto error;
685         }
686         new_buf[new_len]=0; /* debug: print the message */
687         offset=s_offset=0;
688         process_lumps(msg->repl_add_rm, new_buf, &offset, orig, &s_offset);
689         /* copy the rest of the message */
690         memcpy(new_buf+offset,orig+s_offset, len-s_offset);
691          /* send it! */
692         DBG(" copied size: orig:%d, new: %d, rest: %d\n",
693                         s_offset, offset,
694                         len-s_offset );
695
696         *returned_len=new_len;
697         return new_buf;
698 error:
699         *returned_len=0;
700         return 0;
701 }
702
703
704
705
706
707 char * build_res_buf_from_sip_req( unsigned int code, char *text,
708                                         char *new_tag, unsigned int new_tag_len,
709                                         struct sip_msg* msg, unsigned int *returned_len)
710 {
711         char              *buf, *p;
712         unsigned int      len,foo;
713         struct hdr_field  *hdr;
714         struct lump_rpl   *lump;
715         int               i;
716         char              backup;
717         char              *received_buf;
718         char              *rport_buf;
719         unsigned int      received_len;
720         unsigned int      rport_len;
721         unsigned int      delete_len;
722         char              *warning;
723         unsigned int      warning_len;
724         int r;
725 #ifndef PRESERVE_ZT
726         char *after_body;
727 #endif
728         str to_tag;
729
730         received_buf=0;
731         received_len=0;
732         rport_buf=0;
733         rport_len=0;
734         delete_len=0;
735         buf=0;
736         /* make -Wall happy */
737         warning=0;
738
739         /* force parsing all headers -- we want to return all
740         Via's in the reply and they may be scattered down to the
741         end of header (non-block Vias are a really poor property
742         of SIP :( ) */
743         if (parse_headers( msg, HDR_EOH, 0 )==-1) {
744                 LOG(L_ERR, "ERROR: build_res_buf_from_sip_req: "
745                         "alas, parse_headers failed\n");
746                 goto error00;
747         }
748
749         /* check if received needs to be added */
750         backup = msg->via1->host.s[msg->via1->host.len];
751         msg->via1->host.s[msg->via1->host.len] = 0;
752         r=check_address(&msg->rcv.src_ip, msg->via1->host.s, received_dns);
753         msg->via1->host.s[msg->via1->host.len] = backup;
754         if (r!=0) {
755                 if ((received_buf=received_builder(msg,&received_len))==0) {
756                         LOG(L_ERR, "ERROR: build_res_buf_from_sip_req: "
757                                 "alas, received_builder failed\n");
758                         goto error00;
759                 }
760         }
761         /* check if rport needs to be updated */
762         if (msg->via1->rport && msg->via1->rport->value.s==0){
763                 if ((rport_buf=rport_builder(msg, &rport_len))==0){
764                         LOG(L_ERR, "ERROR: build_res_buf_from_sip_req:"
765                                                         " rport_builder failed\n");
766                         goto error01; /* free everything */
767                 }
768                 delete_len=msg->via1->rport->size+1; /* include ';' */
769         }
770
771         /*computes the lenght of the new response buffer*/
772         len = 0;
773         /* first line */
774         len += SIP_VERSION_LEN + 1/*space*/ + 3/*code*/ + 1/*space*/ +
775                 strlen(text) + CRLF_LEN/*new line*/;
776         /*headers that will be copied (TO, FROM, CSEQ,CALLID,VIA)*/
777         for ( hdr=msg->headers ; hdr ; hdr=hdr->next ) {
778                 if (hdr->type==HDR_TO) {
779                         if (new_tag)
780                         {
781                                 to_tag=get_to(msg)->tag_value;
782                                 if (to_tag.s )
783                                         len+=new_tag_len-to_tag.len;
784                                 else
785                                         len+=new_tag_len+TOTAG_TOKEN_LEN/*";tag="*/;
786                         }
787 #ifndef PRESERVE_ZT
788                         else {
789                                 len+=hdr->len;
790                                 continue;
791                         }
792 #endif
793                 } else if (hdr->type==HDR_VIA) {
794                                 if (hdr==msg->h_via1) len += received_len+rport_len;
795                 } else if (hdr->type==HDR_RECORDROUTE) {
796                                 /* RR only for 1xx and 2xx replies */
797                                 if (code<180 || code>=300) continue;
798                 } else if (!(hdr->type==HDR_FROM 
799                                         || hdr->type==HDR_CALLID
800                                         || hdr->type==HDR_CSEQ)) {
801                         continue;
802                 }
803 #ifdef PRESERVE_ZT
804                 len += ((hdr->body.s+hdr->body.len )-hdr->name.s )+CRLF_LEN;
805 #else
806                 len += hdr->len;
807 #endif
808         }
809         len-=delete_len;
810         /*lumps length*/
811         for(lump=msg->reply_lump;lump;lump=lump->next)
812                 len += lump->text.len;
813         if (server_signature) {
814                 /*server header*/
815                 len += SERVER_HDR_LEN + CRLF_LEN;
816                 /*content length header*/
817                 len +=CONTENT_LENGTH_LEN+1 + CRLF_LEN;
818         }
819         if (sip_warning) {
820                 warning = warning_builder(msg,&warning_len);
821                 if (warning) len += warning_len + CRLF_LEN;
822                 else LOG(L_WARN, "WARNING: warning skipped -- too big\n");
823         }
824         /* end of message */
825         len += CRLF_LEN; /*new line*/
826         /*allocating mem*/
827         buf = (char*) pkg_malloc( len+1 );
828         if (!buf)
829         {
830                 LOG(L_ERR, "ERROR: build_res_buf_from_sip_req: out of memory "
831                         " ; needs %d\n",len);
832                 goto error01;
833         }
834
835         /* filling the buffer*/
836         p=buf;
837         /* first line */
838         memcpy( p , SIP_VERSION , SIP_VERSION_LEN );
839         p += SIP_VERSION_LEN;
840         *(p++) = ' ' ;
841         /*code*/
842         for ( i=2 , foo = code  ;  i>=0  ;  i-- , foo=foo/10 )
843                 *(p+i) = '0' + foo - ( foo/10 )*10;
844         p += 3;
845         *(p++) = ' ' ;
846         memcpy( p , text , strlen(text) );
847         p += strlen(text);
848         memcpy( p, CRLF, CRLF_LEN );
849         p+=CRLF_LEN;
850         /* headers*/
851         for ( hdr=msg->headers ; hdr ; hdr=hdr->next )
852                 switch (hdr->type)
853                 {
854                         case HDR_VIA:
855                                 if (hdr==msg->h_via1){
856                                         if (rport_buf){
857                                                 /* copy until rport */
858                                                 append_str_trans( p, hdr->name.s ,
859                                                         msg->via1->rport->start-hdr->name.s-1,msg);
860                                                 /* copy new rport */
861                                                 append_str(p, rport_buf, rport_len);
862                                                 /* copy the rest of the via */
863                                                 append_str_trans(p, msg->via1->rport->start+
864                                                                                         msg->via1->rport->size, 
865                                                                                         hdr->body.s+hdr->body.len-
866                                                                                         msg->via1->rport->start-
867                                                                                         msg->via1->rport->size, msg);
868                                         }else{
869                                                 /* normal whole via copy */
870                                                 append_str_trans( p, hdr->name.s ,
871                                                         ((hdr->body.s+hdr->body.len )-hdr->name.s ), msg);
872                                         }
873                                         if (received_buf)
874                                                 append_str( p, received_buf, received_len);
875                                 }else{
876                                         /* normal whole via copy */
877                                         append_str_trans( p, hdr->name.s ,
878                                                 ((hdr->body.s+hdr->body.len )-hdr->name.s ),msg);
879                                 }
880                                 append_str( p, CRLF,CRLF_LEN);
881                                 break;
882                         case HDR_RECORDROUTE:
883                                 /* RR only for 1xx and 2xx replies */
884                                 if (code<180 || code>=300) break;
885                         case HDR_TO:
886                                 if (new_tag){
887                                         if (to_tag.s ) { /* replacement */
888 #ifdef PRESERVE_ZT
889                                                 /* before to-tag */
890                                                 append_str_trans( p, hdr->name.s ,
891                                                         to_tag.s-hdr->name.s,msg);
892                                                 /* to tag replacement */
893                                                 append_str( p, new_tag,new_tag_len);
894                                                 /* the rest after to-tag */
895                                                 append_str_trans( p,to_tag.s+to_tag.len,
896                                                         ((hdr->body.s+hdr->body.len )-
897                                                         (to_tag.s+to_tag.len)),msg);
898                                                 append_str( p, CRLF,CRLF_LEN);
899 #else
900                                                 /* before to-tag */
901                                                 append_str( p, hdr->name.s, to_tag.s-hdr->name.s);
902                                                 /* to tag replacement */
903                                                 append_str( p, new_tag,new_tag_len);
904                                                 /* the rest after to-tag */
905                                                 append_str( p, to_tag.s+to_tag.len,
906                                                         hdr->name.s+hdr->len-(to_tag.s+to_tag.len));
907 #endif
908                                         }else{ /* adding a new to-tag */
909 #ifdef PRESERVE_ZT
910                                                 append_str_trans( p, hdr->name.s ,
911                                                         ((hdr->body.s+hdr->body.len )-hdr->name.s ),
912                                                         msg);
913                                                 append_str( p, TOTAG_TOKEN,TOTAG_TOKEN_LEN);
914                                                 append_str( p, new_tag,new_tag_len);
915                                                 append_str( p, CRLF,CRLF_LEN);
916 #else
917                                                 after_body=hdr->body.s+hdr->body.len;
918                                                 append_str( p, hdr->name.s, after_body-hdr->name.s);
919                                                 append_str(p, TOTAG_TOKEN, TOTAG_TOKEN_LEN);
920                                                 append_str( p, new_tag,new_tag_len);
921                                                 append_str( p, after_body, 
922                                                                                 hdr->name.s+hdr->len-after_body);
923 #endif
924                                         }
925                                         break;
926                                 } /* no new to-tag -- proceed to 1:1 copying  */
927                         case HDR_FROM:
928                         case HDR_CALLID:
929                         case HDR_CSEQ:
930 #ifdef PRESERVE_ZT
931                                         append_str_trans( p, hdr->name.s ,
932                                                 ((hdr->body.s+hdr->body.len )-hdr->name.s ),msg);
933                                         append_str( p, CRLF,CRLF_LEN);
934 #else
935                                         append_str(p, hdr->name.s, hdr->len);
936 #endif
937                 } /* for switch */
938         /*lumps*/
939         for(lump=msg->reply_lump;lump;lump=lump->next)
940         {
941                 memcpy(p,lump->text.s,lump->text.len);
942                 p += lump->text.len;
943         }
944         if (server_signature) {
945                 /*server header*/
946                 memcpy( p, SERVER_HDR , SERVER_HDR_LEN );
947                 p+=SERVER_HDR_LEN;
948                 memcpy( p, CRLF, CRLF_LEN );
949                 p+=CRLF_LEN;
950                 /* content length header*/
951                 memcpy( p, CONTENT_LENGTH "0" , CONTENT_LENGTH_LEN+1 );
952                 p+=CONTENT_LENGTH_LEN+1;
953                 memcpy( p, CRLF, CRLF_LEN );
954                 p+=CRLF_LEN;
955         }
956         if (sip_warning && warning) {
957                 memcpy( p, warning, warning_len);
958                 p+=warning_len;
959                 memcpy( p, CRLF, CRLF_LEN);
960                 p+=CRLF_LEN;
961         }
962         /*end of message*/
963         memcpy( p, CRLF, CRLF_LEN );
964         p+=CRLF_LEN;
965         *(p) = 0;
966         *returned_len = len;
967         /* in req2reply, received_buf is not introduced to lumps and
968            needs to be deleted here
969         */
970         if (received_buf) pkg_free(received_buf);
971         if (rport_buf) pkg_free(rport_buf);
972         return buf;
973
974 error01:
975         if (received_buf) pkg_free(received_buf);
976         if (rport_buf) pkg_free(rport_buf);
977 error00:
978         *returned_len=0;
979         return 0;
980 }
981
982 /* return number of chars printed or 0 if space exceeded;
983    assumes buffer sace of at least MAX_BRANCH_PARAM_LEN
984  */
985
986 int branch_builder( unsigned int hash_index,
987         /* only either parameter useful */
988         unsigned int label, char * char_v,
989         int branch,
990         char *branch_str, int *len )
991 {
992
993         char *begin;
994         int size;
995
996 #ifdef _OBSOLETED
997         /* no hash_id --- whoever called me wants to have
998            very simple branch_id
999         */
1000         if (hash_index==0) {
1001                 *branch_str='0';
1002                 *len=1;
1003                 return *len;
1004         }
1005 #endif
1006
1007         /* hash id provided ... start with it */
1008         size=MAX_BRANCH_PARAM_LEN;
1009         begin=branch_str;
1010         *len=0;
1011
1012         memcpy(begin, MCOOKIE, MCOOKIE_LEN );
1013         size-=MCOOKIE_LEN;begin+=MCOOKIE_LEN;
1014
1015         if (int2reverse_hex( &begin, &size, hash_index)==-1)
1016                 return 0;
1017
1018         if (size) {
1019                 *begin=BRANCH_SEPARATOR;
1020                 begin++; size--;
1021         } else return 0;
1022
1023         /* string with request's characteristic value ... use it ... */
1024         if (char_v) {
1025                 if (memcpy(begin,char_v,MD5_LEN)) {
1026                         begin+=MD5_LEN; size-=MD5_LEN;
1027                 } else return 0;
1028         } else { /* ... use the "label" value otherwise */
1029                 if (int2reverse_hex( &begin, &size, label )==-1)
1030                         return 0;
1031         }
1032
1033         if (size) {
1034                 *begin=BRANCH_SEPARATOR;
1035                 begin++; size--;
1036         } else return 0;
1037
1038         if (int2reverse_hex( &begin, &size, branch)==-1)
1039                 return 0;
1040
1041         *len=MAX_BRANCH_PARAM_LEN-size;
1042         return size;
1043                 
1044 }
1045
1046
1047 char* via_builder( unsigned int *len, 
1048         struct socket_info* send_sock,
1049         str* branch, str* extra_params, int proto )
1050 {
1051         unsigned int  via_len, extra_len;
1052         char               *line_buf;
1053         int max_len;
1054
1055
1056         max_len=MY_VIA_LEN+send_sock->address_str.len /* space in MY_VIA */
1057                 +2 /* just in case it is a v6 address ... [ ] */
1058                 +send_sock->port_no_str.len
1059                 +(branch?(MY_BRANCH_LEN+branch->len):0)
1060                 +(extra_params?extra_params->len:0)
1061                 +CRLF_LEN+1;
1062         line_buf=pkg_malloc( max_len );
1063         if (line_buf==0){
1064                 ser_error=E_OUT_OF_MEM;
1065                 LOG(L_ERR, "ERROR: via_builder: out of memory\n");
1066                 return 0;
1067         }
1068
1069         extra_len=0;
1070
1071         via_len=MY_VIA_LEN+send_sock->address_str.len; /*space included in MY_VIA*/
1072
1073         memcpy(line_buf, MY_VIA, MY_VIA_LEN-4); /* without "UPD " */
1074         if (proto==PROTO_UDP)
1075                 memcpy(line_buf+MY_VIA_LEN-4, "UDP ", 4);
1076         else if (proto==PROTO_TCP)
1077                 memcpy(line_buf+MY_VIA_LEN-4, "TCP ", 4);
1078         else{
1079                 LOG(L_CRIT, "BUG: via_builder: unknown proto %d\n", proto);
1080                 return 0;
1081         }
1082 #       ifdef USE_IPV6
1083         if (send_sock->address.af==AF_INET6) {
1084                 line_buf[MY_VIA_LEN]='[';
1085                 line_buf[MY_VIA_LEN+1+send_sock->address_str.len]=']';
1086                 extra_len=1;
1087                 via_len+=2; /* [ ]*/
1088         }
1089 #       endif
1090         memcpy(line_buf+MY_VIA_LEN+extra_len, send_sock->address_str.s,
1091                 send_sock->address_str.len);
1092         if (send_sock->port_no!=SIP_PORT){
1093                 memcpy(line_buf+via_len, send_sock->port_no_str.s,
1094                          send_sock->port_no_str.len);
1095                 via_len+=send_sock->port_no_str.len;
1096         }
1097
1098         /* branch parameter */
1099         if (branch){
1100                 memcpy(line_buf+via_len, MY_BRANCH, MY_BRANCH_LEN );
1101                 via_len+=MY_BRANCH_LEN;
1102                 memcpy(line_buf+via_len, branch->s, branch->len );
1103                 via_len+=branch->len;
1104         }
1105         /* extra params  */
1106         if (extra_params){
1107                 memcpy(line_buf+via_len, extra_params->s, extra_params->len);
1108                 via_len+=extra_params->len;
1109         }
1110         
1111         memcpy(line_buf+via_len, CRLF, CRLF_LEN);
1112         via_len+=CRLF_LEN;
1113         line_buf[via_len]=0; /* null terminate the string*/
1114
1115         *len = via_len;
1116         return line_buf;
1117 }