rem: len += CONTENT_LENGTH_LEN + 1 + CRLF_LEN;
context: char * build_res_buf_from_sip_req( unsigned int code, char *text ,str *new_tag,		struct sip_msg* msg, unsigned int *returned_len, struct bookmark *bmark){	char              *buf, *p;	unsigned int      len,foo;	struct hdr_field  *hdr;	struct lump_rpl   *lump;	struct lump_rpl   *body;	int               i;	char              backup;	str               received = {0,0};	str               rport = {0,0};	str               warning = {0,0};	str               content_len = {0,0};	unsigned int      text_len;	char *after_body;	str  to_tag;	char *totags;	int rcvd;	body = 0;	buf=0;	text_len=strlen(text);	/* force parsing all headers -- we want to return all	Via's in the reply and they may be scattered down to the	end of header (non-block Vias are a really poor property	of SIP :( ) */	if (parse_headers( msg, HDR_EOH, 0 )==-1) {		LOG(L_ERR, "ERROR: build_res_buf_from_sip_req: "			"alas, parse_headers failed\n");		goto error00;	}	/*computes the lenght of the new response buffer*/	len = 0;	/* check if received needs to be added */	backup = msg->via1->host.s[msg->via1->host.len];	msg->via1->host.s[msg->via1->host.len] = 0;	rcvd=msg->via1->received 			|| check_via_address(&msg->rcv.src_ip, &msg->via1->host, 						msg->via1->port, received_dns);	msg->via1->host.s[msg->via1->host.len] = backup;	if (rcvd) {		if ((received.s=received_builder(msg,&received.len))==0) {			LOG(L_ERR, "ERROR: build_res_buf_from_sip_req: "				"alas, received_builder failed\n");			goto error00;		}	}	/* check if rport needs to be updated */	if ( (msg->msg_flags&FL_FORCE_RPORT)||		(msg->via1->rport /*&& msg->via1->rport->value.s==0*/)){		if ((rport.s=rport_builder(msg, &rport.len))==0){			LOG(L_ERR, "ERROR: build_res_buf_from_sip_req:"							" rport_builder failed\n");			goto error01; /* free everything */		}		if (msg->via1->rport) 			len -= msg->via1->rport->size+1; /* include ';' */	}	/* first line */	len += SIP_VERSION_LEN + 1/*space*/ + 3/*code*/ + 1/*space*/ +		text_len + CRLF_LEN/*new line*/;	/*headers that will be copied (TO, FROM, CSEQ,CALLID,VIA)*/	for ( hdr=msg->headers ; hdr ; hdr=hdr->next ) {		switch (hdr->type) {			case HDR_TO:				if (new_tag && new_tag->len) {					to_tag=get_to(msg)->tag_value;					if (to_tag.len )						len+=new_tag->len-to_tag.len;					else						len+=new_tag->len+TOTAG_TOKEN_LEN/*";tag="*/;				}				len += hdr->len;				break;			case HDR_VIA:				/* we always add CRLF to via*/				len+=(hdr->body.s+hdr->body.len)-hdr->name.s+CRLF_LEN;				if (hdr==msg->h_via1) len += received.len+rport.len;				break;			case HDR_RECORDROUTE:				/* RR only for 1xx and 2xx replies */				if (code<180 || code>=300)					break;			case HDR_FROM:			case HDR_CALLID:			case HDR_CSEQ:				/* we keep the original termination for these headers*/				len += hdr->len;		}	}	/* lumps length */	for(lump=msg->reply_lump;lump;lump=lump->next) {		len += lump->text.len;		if (lump->type==LUMP_RPL_BODY && lump->text.s && lump->text.len)			body = lump;	}	/* server header */	if (server_signature)		len += SERVER_HDR_LEN + CRLF_LEN;	/* warning hdr */	if (sip_warning) {		warning.s = warning_builder(msg,&warning.len);		if (warning.s) len += warning.len + CRLF_LEN;		else LOG(L_WARN, "WARNING: warning skipped -- too big\n");	}	/* content length hdr */	len += CONTENT_LENGTH_LEN + 1/*0*/ + CRLF_LEN;	/* body */	if (body) {		content_len.s = int2str(body->text.len, &content_len.len);		len += content_len.len - 1 + body->text.len;	}	/* end of message */	len += CRLF_LEN; /*new line*/	/*allocating mem*/	buf = (char*) pkg_malloc( len+1 );	if (!buf)	{		LOG(L_ERR, "ERROR: build_res_buf_from_sip_req: out of memory "			" ; needs %d\n",len);		goto error01;	}	/* filling the buffer*/	p=buf;	/* first line */	memcpy( p , SIP_VERSION , SIP_VERSION_LEN );	p += SIP_VERSION_LEN;	*(p++) = ' ' ;	/*code*/	for ( i=2 , foo = code  ;  i>=0  ;  i-- , foo=foo/10 )		*(p+i) = '0' + foo - ( foo/10 )*10;	p += 3;	*(p++) = ' ' ;	memcpy( p , text , text_len );	p += text_len;	memcpy( p, CRLF, CRLF_LEN );	p+=CRLF_LEN;	/* headers*/	for ( hdr=msg->headers ; hdr ; hdr=hdr->next ) {		switch (hdr->type)		{			case HDR_VIA:				if (hdr==msg->h_via1){					if (rport.s){						if (msg->via1->rport){ /* delete the old one */							/* copy until rport */							append_str_trans( p, hdr->name.s ,								msg->via1->rport->start-hdr->name.s-1,msg);							/* copy new rport */							append_str(p, rport.s, rport.len);							/* copy the rest of the via */							append_str_trans(p, msg->via1->rport->start+												msg->via1->rport->size, 												hdr->body.s+hdr->body.len-												msg->via1->rport->start-												msg->via1->rport->size, msg);						}else{ /* just append the new one */							/* normal whole via copy */							append_str_trans( p, hdr->name.s , 								(hdr->body.s+hdr->body.len)-hdr->name.s, msg);							append_str(p, rport.s, rport.len);						}					}else{						/* normal whole via copy */						append_str_trans( p, hdr->name.s , 								(hdr->body.s+hdr->body.len)-hdr->name.s, msg);					}					if (received.s)						append_str( p, received.s, received.len);				}else{					/* normal whole via copy */					append_str_trans( p, hdr->name.s,							(hdr->body.s+hdr->body.len)-hdr->name.s, msg);				}				append_str( p, CRLF,CRLF_LEN);				break;			case HDR_RECORDROUTE:				/* RR only for 1xx and 2xx replies */				if (code<180 || code>=300) break;				append_str(p, hdr->name.s, hdr->len);				break;			case HDR_TO:				if (new_tag && new_tag->len){					if (to_tag.s ) { /* replacement */						/* before to-tag */						append_str( p, hdr->name.s, to_tag.s-hdr->name.s);						/* to tag replacement */						bmark->to_tag_val.s=p;						bmark->to_tag_val.len=new_tag->len;						append_str( p, new_tag->s,new_tag->len);						/* the rest after to-tag */						append_str( p, to_tag.s+to_tag.len,							hdr->name.s+hdr->len-(to_tag.s+to_tag.len));					}else{ /* adding a new to-tag */						after_body=hdr->body.s+hdr->body.len;						append_str( p, hdr->name.s, after_body-hdr->name.s);						append_str(p, TOTAG_TOKEN, TOTAG_TOKEN_LEN);						bmark->to_tag_val.s=p;						bmark->to_tag_val.len=new_tag->len;						append_str( p, new_tag->s,new_tag->len);						append_str( p, after_body, 										hdr->name.s+hdr->len-after_body);					}					break;				} /* no new to-tag -- proceed to 1:1 copying  */				totags=((struct to_body*)(hdr->parsed))->tag_value.s;				if (totags) {					bmark->to_tag_val.s=p+(totags-hdr->name.s);					bmark->to_tag_val.len=							((struct to_body*)(hdr->parsed))->tag_value.len;				};			case HDR_FROM:			case HDR_CALLID:			case HDR_CSEQ:					append_str(p, hdr->name.s, hdr->len);		} /* end switch */	} /* end for */	/* lumps */	for(lump=msg->reply_lump;lump;lump=lump->next)		if (lump->type==LUMP_RPL_HDR){			memcpy(p,lump->text.s,lump->text.len);			p += lump->text.len;		}	/* server header */	if (server_signature) {		memcpy( p, SERVER_HDR , SERVER_HDR_LEN );		p+=SERVER_HDR_LEN;		memcpy( p, CRLF, CRLF_LEN );		p+=CRLF_LEN;	}	/* content_length hdr */	memcpy(p, CONTENT_LENGTH, CONTENT_LENGTH_LEN );	p+=CONTENT_LENGTH_LEN;	if (content_len.len) {		memcpy( p, content_len.s, content_len.len );		p+=content_len.len;	} else {		*(p++) = '0';	}	memcpy( p, CRLF, CRLF_LEN );	p+=CRLF_LEN;	/* warning header */	if (warning.s) {		memcpy( p, warning.s, warning.len);		p+=warning.len;		memcpy( p, CRLF, CRLF_LEN);		p+=CRLF_LEN;	}	/*end of message*/	memcpy( p, CRLF, CRLF_LEN );	p+=CRLF_LEN;	/* body */	if (body) {		memcpy ( p, body->text.s, body->text.len );		p+=body->text.len;	}	if (len!=p-buf)		LOG(L_CRIT,"BUGGGG!!!! diff len=%d p-buf=%d\n",len,p-buf);	*(p) = 0;	*returned_len = len;	/* in req2reply, received_buf is not introduced to lumps and	   needs to be deleted here	*/	if (received.s) pkg_free(received.s);	if (rport.s) pkg_free(rport.s);	return buf;error01:	if (received.s) pkg_free(received.s);	if (rport.s) pkg_free(rport.s);error00:	*returned_len=0;	return 0;}