Exemple #1
0
int dlg_th_encode_callid(struct sip_msg *msg)
{
	struct lump *del;
	str new_callid;
	int i;

	if (msg->callid == NULL) {
		LM_ERR("Message with no callid\n");
		return -1;
	}

	new_callid.len = calc_base64_encode_len(msg->callid->body.len);
	new_callid.len += topo_hiding_prefix.len;
	new_callid.s = pkg_malloc(new_callid.len);
	if (new_callid.s==NULL) {
		LM_ERR("Failed to allocate callid len\n");
		return -1;
	}

	if (new_callid.s == NULL) {
		LM_ERR("Failed to encode callid\n");
		return -1;
	}

	memcpy(new_callid.s,topo_hiding_prefix.s,topo_hiding_prefix.len);
	for (i=0;i<msg->callid->body.len;i++)
		msg->callid->body.s[i] ^= topo_hiding_seed.s[i%topo_hiding_seed.len]; 

	base64encode((unsigned char *)(new_callid.s+topo_hiding_prefix.len),
		     (unsigned char *)(msg->callid->body.s),msg->callid->body.len);

	/* reset the callid back to original value - some might still need it ( eg. post script )
	FIXME : use bigger buffer here ? mem vs cpu */
	for (i=0;i<msg->callid->body.len;i++)
		msg->callid->body.s[i] ^= topo_hiding_seed.s[i%topo_hiding_seed.len]; 

	del=del_lump(msg, msg->callid->body.s-msg->buf, msg->callid->body.len, HDR_CALLID_T);
	if (del==NULL) {               
		LM_ERR("Failed to delete old callid\n");
		pkg_free(new_callid.s);
		return -1;
	}

	if (insert_new_lump_after(del,new_callid.s,new_callid.len,HDR_CALLID_T)==NULL) {
		LM_ERR("Failed to insert new callid\n");
		pkg_free(new_callid.s);
		return -1;
	}

	return 0;
}
Exemple #2
0
static int pv_topo_callee_callid(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
{
	struct dlg_cell *dlg;
	int req_len = 0,i;
	char *p;

	if(res==NULL)
		return -1;

	if ( (dlg=dlg_api.get_dlg())==NULL || 
	(!dlg_api.is_mod_flag_set(dlg,TOPOH_HIDE_CALLID))) {
		return pv_get_null( msg, param, res);
	}


	req_len = calc_base64_encode_len(dlg->callid.len) + topo_hiding_prefix.len;

	if (req_len*2 > callid_buf_len) {
		callid_buf = pkg_realloc(callid_buf,req_len*2);
		if (callid_buf == NULL) {
			LM_ERR("No more pkg\n");
			return pv_get_null( msg, param, res);
		}

		callid_buf_len = req_len*2;
	}

	memcpy(callid_buf+req_len,topo_hiding_prefix.s,topo_hiding_prefix.len);
	for (i=0;i<dlg->callid.len;i++)
		callid_buf[i] = dlg->callid.s[i] ^ topo_hiding_seed.s[i%topo_hiding_seed.len];

	base64encode((unsigned char *)(callid_buf+topo_hiding_prefix.len+req_len),
		     (unsigned char *)(callid_buf),dlg->callid.len);

	p = callid_buf+ 2*req_len - 1;
	while (*p == '=') {
		*p = '-';
		p--;
	}

	res->rs.s = callid_buf+req_len;
	res->rs.len = req_len;
	res->flags = PV_VAL_STR;

	return 0;
}
Exemple #3
0
static char* serialize_dns_rdata(struct rdata *head,int buf_len,int *len,int do_encoding)
{
	unsigned char *p;
	struct rdata *it;
	int needed_len;
	int entry_len,base64_len=0;
	struct cname_rdata *cname_rd;
	struct srv_rdata *srv_rd;
	struct naptr_rdata *naptr_rd;
	struct ebl_rdata *ebl_rd;
	struct txt_rdata *txt_rd;

	if (do_encoding) {
		base64_len = calc_base64_encode_len(buf_len);
		needed_len = buf_len + base64_len; 
	} else {
		needed_len = buf_len;
	}	

	if (rdata_buf == NULL || needed_len > rdata_buf_len) {
		rdata_buf = pkg_realloc(rdata_buf,needed_len);	
		if (rdata_buf == NULL) {
			LM_ERR("No more pkg\n");
			return NULL;				
		}
		rdata_buf_len = needed_len;
	}

	p = rdata_buf;
	
	for (it=head;it;it=it->next) {
		/* copy non-pointer fields of the struct */
		memcpy(p,it,rdata_struct_len);
		p+=rdata_struct_len;
		
		switch (it->type) {
			case T_A:
				/* copy all 4 bytes */
				memcpy(p,it->rdata,sizeof(struct a_rdata));
				p+=sizeof(struct a_rdata);
				break;				
			case T_AAAA:
				/* copy all 16 bytes */
				memcpy(p,it->rdata,sizeof(struct aaaa_rdata));
				p+=sizeof(struct aaaa_rdata);
				break;				
			case T_CNAME:
				cname_rd=(struct cname_rdata *)it->rdata;
				entry_len=strlen(cname_rd->name);
				/* copy len of alias */
				memcpy(p,&entry_len,sizeof(int));
				p+=sizeof(int);
				/* copy alias */
				memcpy(p,cname_rd->name,entry_len+1);
				p+=entry_len+1;
				break;				
			case T_NAPTR:
				/* copy priority, etc */
				memcpy(p,it->rdata,2*sizeof(unsigned short) + 
						sizeof(unsigned int)); 
				p+=2*sizeof(unsigned short) + sizeof(unsigned int);
				naptr_rd=it->rdata;
				/* copy flags, flags_len was copied above */
				memcpy(p,naptr_rd->flags,naptr_rd->flags_len+1);
				p+=naptr_rd->flags_len+1;
				/* copy services & len */
				memcpy(p,&naptr_rd->services_len,sizeof(unsigned int));
				p+=sizeof(unsigned int);
				memcpy(p,naptr_rd->services,naptr_rd->services_len+1);
				p+=naptr_rd->services_len+1;
				/* copy regexp & len */
				memcpy(p,&naptr_rd->regexp_len,sizeof(unsigned int));
				p+=sizeof(unsigned int);
				memcpy(p,naptr_rd->regexp,naptr_rd->regexp_len+1);
				p+=naptr_rd->regexp_len+1;
				/* copy repl & len */
				memcpy(p,&naptr_rd->repl_len,sizeof(unsigned int));
				p+=sizeof(unsigned int);
				memcpy(p,naptr_rd->repl,naptr_rd->repl_len+1);
				p+=naptr_rd->repl_len+1;
				break;				
			case T_SRV:
				srv_rd=it->rdata;
				memcpy(p,srv_rd,4*sizeof(unsigned short) +
					sizeof(unsigned int));
				p+=4*sizeof(unsigned short) + sizeof(unsigned int);
				memcpy(p,srv_rd->name,srv_rd->name_len+1);
				p+=srv_rd->name_len+1;
				break;				
			case T_TXT:
				txt_rd=it->rdata;
				entry_len=strlen(txt_rd->txt);
				memcpy(p,&entry_len,sizeof(int));
				p+=sizeof(int);
				memcpy(p,txt_rd->txt,entry_len+1);
				p+=entry_len+1;		
				break;				
			case T_EBL:
				ebl_rd=it->rdata;
				memcpy(p,ebl_rd,sizeof(unsigned char) + 
					sizeof(unsigned int));
				p+=sizeof(unsigned char) + sizeof(unsigned int);
				memcpy(p,ebl_rd->separator,ebl_rd->separator_len+1);
				p+=ebl_rd->separator_len+1;
				memcpy(p,&ebl_rd->apex_len,sizeof(unsigned int));
				p+=sizeof(unsigned int);
				memcpy(p,ebl_rd->apex,ebl_rd->apex_len+1);
				p+=ebl_rd->apex_len+1;
				break;				
			default:
				LM_ERR("Unexpected DNS record type\n");
				return NULL;
		}
	}
	
	if (do_encoding) {
		if (*len)
			*len = base64_len;

		/* encode and return beggining of encoding */
		base64encode(p,rdata_buf,buf_len);
		return (char *)p;	
	} else { 
		if (*len)
			*len = needed_len;
		return (char *)rdata_buf;
	}
}
Exemple #4
0
static char* serialize_he_rdata(struct hostent *he,int *buf_len,int do_encoding)
{
	unsigned char *p;
	int i,len=0,needed_len=0,base64_len=0,alias_no=0,addr_no=0;

	/* addr_type, name_len, alias_no, addr_no */ 
	len+=sizeof(int)*4;

	/* compute needed buffer length */
	if (he->h_name)
		len+=strlen(he->h_name)+1;

	if (he->h_aliases)
       		for (i=0;he->h_aliases[i];i++) {
			/* integer with len + len bytes of alias */
			len+=strlen(he->h_aliases[i])+1+sizeof(int);
			alias_no++;
		}


	i=0;
	if (he->h_addr_list)
       		for (i=0;he->h_addr_list[i];i++) {
			len+=he->h_length;
			addr_no++;
		}

	if (do_encoding) {
		/* backend does not support binary values - allocate continous buffer
		for encoding */
		base64_len = calc_base64_encode_len(len);
		needed_len=len+base64_len;
	} else
		needed_len = len;	

	if (he_buf == NULL || needed_len > he_buf_len) {
		/* realloc if not enough space */
		he_buf = pkg_realloc(he_buf,needed_len);	
		if (he_buf == NULL) {
			LM_ERR("No more pkg\n");
			return NULL;				
		}
		he_buf_len = needed_len;
	}

	p = he_buf;

	/* copy address type */
	memcpy(p,&he->h_addrtype,sizeof(int));
	p+=sizeof(int);

	/* copy h_name len */
	len=strlen(he->h_name)+1;			
	memcpy(p,&len,sizeof(int));
	p+=sizeof(int);
	/* copy h_name */
	memcpy(p,he->h_name,len);
	p+=len;
	
	/* copy number of aliases */
	memcpy(p,&alias_no,sizeof(int));
	p+=sizeof(int);

	/* copy aliases, if any */
	if (he->h_aliases)
       		for (i=0;he->h_aliases[i];i++) {
			len=strlen(he->h_aliases[i])+1;
			/* copy alias length */
			memcpy(p,&len,sizeof(int));
			p+=sizeof(int);
			/* copy alias */
			memcpy(p,he->h_aliases[i],len);
			p+=len;
		}

	/* copy address no */
	memcpy(p,&addr_no,sizeof(int));
	p+=sizeof(int);

	/* copy addresses */
	if (he->h_addr_list)
       		for (i=0;he->h_addr_list[i];i++) {
			/* copy addreses. length will be known from the addrtype field */
			len=he->h_length;
			memcpy(p,he->h_addr_list[i],len);
			p+=len;
		}

	if (do_encoding) {
		len = needed_len - base64_len;

		if (buf_len)
			*buf_len=base64_len;

		/* do encoding, and return pointer after unencoded data */
		base64encode(p,he_buf,len);
		return (char *)p;	
	} else {
		if (buf_len)
			*buf_len = needed_len;
		return (char *)he_buf;	
	}
}
Exemple #5
0
int mc_compress_cb(char** buf_p, void* param, int type, int* olen)
{
	int rc;
	int len;
	int algo;
	int flags;
	int compress_len=0;
	int uncompress_len=0;
	int hdr_compress_len=0;

	str msg_start;

	char *buf=*buf_p;
	char *end=buf+strlen(buf);
	unsigned long temp;
	struct mc_comp_args *args=(struct mc_comp_args*)param;

	struct hdr_field *hf;
	struct hdr_field *mnd_hdrs=NULL;
	struct hdr_field *non_mnd_hdrs=NULL;
	struct hdr_field *mnd_hdrs_head=NULL;
	struct hdr_field *non_mnd_hdrs_head=NULL;

	mc_param_p wh_param;
	mc_whitelist_p hdr2compress_list;

	wh_param = args->wh_param;
	hdr2compress_list = args->hdr2compress_list;
	algo = args->algo;
	flags = args->flags;

	mc_parse_first_line(&msg_start, &buf);

	uncompress_len = msg_start.len;

	/* Parse the message until the body is found
		Build two lists one of mandatory headers and one
			of non mandatory headers */

	while (1) {
		hf = pkg_malloc(sizeof(struct hdr_field));
		if (hf == NULL) {
			LM_ERR("no more pkg mem\n");
			goto free_mem_full;
		}
		memset(hf, 0, sizeof(struct hdr_field));
		hf->type=HDR_ERROR_T;
		buf=get_hdr_field(buf, end, hf);

		if (hf->type == HDR_ERROR_T) {
			goto free_mem_full;
		}

		if (hf->type == HDR_EOH_T) {
			compress_len += strlen(buf);
			compress_len = compress_len > CRLF_LEN ? compress_len : 0;
			pkg_free(hf);
			break;
		}

		/*if Content-Length=0 then header must remain*/
		if (hf->type == HDR_CONTENTLENGTH_T &&
				hf->body.s[0] == '0') {
			goto set_mandatory;
		}

		if (mc_is_in_whitelist(hf, hdr2compress_list)) {
			if (!non_mnd_hdrs) {
				non_mnd_hdrs_head = non_mnd_hdrs = hf;
			} else {
				non_mnd_hdrs->next = hf;
				non_mnd_hdrs = non_mnd_hdrs->next;
			}

			/* in case will have a separate compressed header */
			if ((flags&SEPARATE_COMP_FLG && flags&BODY_COMP_FLG &&
							flags&HDR_COMP_FLG) ||
				(flags&HDR_COMP_FLG && !(flags&BODY_COMP_FLG)))
				hdr_compress_len += hf->len;
			else
				compress_len += hf->len;

		} else {
		set_mandatory:
			if (!mnd_hdrs) {
				mnd_hdrs_head = mnd_hdrs = hf;
			} else {
				mnd_hdrs->next = hf;
				mnd_hdrs = mnd_hdrs->next;
			}
			uncompress_len += hf->len;
		}
		hf = 0;
	}

	str buf2compress={NULL, 0};
	str hdr_buf2compress={NULL, 0};

	/* Copy headers only if they exist and only if were asked*/
	non_mnd_hdrs = non_mnd_hdrs_head;
	if (!non_mnd_hdrs || !(flags&HDR_COMP_FLG))
		goto only_body;

	/* If body compression and header compression flags are set and
		they have to be together in the body */
	if ((flags&BODY_COMP_FLG && flags&HDR_COMP_FLG &&
						!(flags&SEPARATE_COMP_FLG)) ||
		(flags&BODY_COMP_FLG && !(flags&HDR_COMP_FLG))){

		if (wrap_realloc(&body_in, compress_len))
			goto free_mem_full;

		buf2compress.s = body_in.s;
		buf2compress.len = 0;

		for (hf = non_mnd_hdrs; hf; hf = hf->next) {
			wrap_copy_and_update( &buf2compress.s, hf->name.s,
						hf->len, &buf2compress.len);
		}
	/* body compression and header compression but separately or
		only header compression */
	} else if ((flags&BODY_COMP_FLG && flags&HDR_COMP_FLG &&
			flags&SEPARATE_COMP_FLG) ||
		    (!(flags&BODY_COMP_FLG) && flags&HDR_COMP_FLG)) {

		if (wrap_realloc(&hdr_in, hdr_compress_len))
			goto free_mem_full;

		hdr_buf2compress.s = hdr_in.s;

		for (hf = non_mnd_hdrs; hf; hf = hf->next) {
			wrap_copy_and_update( &hdr_buf2compress.s, hf->name.s,
						hf->len, &hdr_buf2compress.len);
		}
	}

only_body:
	/* Copy the body of the message only if body compression is asked */
	if (flags&BODY_COMP_FLG && compress_len) {
		if (!buf2compress.s) {
			if (wrap_realloc(&body_in, compress_len))
				goto free_mem_full;
			buf2compress.s = body_in.s;
		}

		wrap_copy_and_update( &buf2compress.s, buf, strlen(buf),
							&buf2compress.len);
	}

	if (!buf2compress.s && !hdr_buf2compress.s) {
		LM_WARN("Nothing to compress. Specified headers not found\n");
		goto free_mem_full;
	}

	/* Compress the message */
	str bufcompressed={NULL, 0};
	str hdr_bufcompressed={NULL, 0};

	switch (algo) {
	case 0: /* deflate */

		if (buf2compress.s) {
			bufcompressed.len = compressBound((unsigned long)buf2compress.len);
			if (wrap_realloc(&body_out, bufcompressed.len))
				goto free_mem_full;

			bufcompressed.s = body_out.s;
			temp = (unsigned long)bufcompressed.len;

			rc = compress2((unsigned char*)bufcompressed.s,
					&temp,
					(unsigned char*)buf2compress.s,
					(unsigned long)buf2compress.len,
					mc_level);

			bufcompressed.len = (int)temp;

			if (check_zlib_rc(rc)) {
				LM_ERR("Body compression failed\n");
				goto free_mem_full;
			}
		}

		if ((flags&HDR_COMP_FLG) && hdr_buf2compress.s) {
			hdr_bufcompressed.len = compressBound((unsigned long)hdr_buf2compress.len);
			if (wrap_realloc(&hdr_out, hdr_bufcompressed.len))
				goto free_mem_full;

			hdr_bufcompressed.s = hdr_out.s;
			temp = (unsigned long)hdr_bufcompressed.len;

			rc = compress2((unsigned char*)hdr_bufcompressed.s,
					&temp,
					(unsigned char*)hdr_buf2compress.s,
					(unsigned long)hdr_buf2compress.len,
					mc_level);

			hdr_bufcompressed.len = temp;

			if (check_zlib_rc(rc)) {
				LM_ERR("Header compression failed\n");
				goto free_mem_full;
			}
		}

		break;
	case 1: /* gzip */
		if (buf2compress.s) {
			rc = gzip_compress(
					(unsigned char*)buf2compress.s,
					(unsigned long)buf2compress.len,
					&body_out,
					&temp,
					mc_level);

			if (check_zlib_rc(rc)) {
				LM_ERR("Body compression failed\n");
				goto free_mem_full;
			}

			bufcompressed.s = body_out.s;
			bufcompressed.len = (int)temp;
		}

		if ((flags&HDR_COMP_FLG) && hdr_buf2compress.s) {
			rc = gzip_compress(
					(unsigned char*)hdr_buf2compress.s,
					(unsigned long)hdr_buf2compress.len,
					&hdr_out,
					&temp,
					mc_level);

			if (check_zlib_rc(rc)) {
				LM_ERR("Header compression failed\n");
				goto free_mem_full;
			}
			hdr_bufcompressed.s = hdr_out.s;
			hdr_bufcompressed.len = temp;
		}

		break;
	default:
		LM_WARN("Invalind algo! no compression made\n");
		goto free_mem_full;
	}

	str bufencoded={NULL, 0};
	str hdr_bufencoded={NULL, 0};

	if ((flags&B64_ENCODED_FLG) && bufcompressed.s) {
		bufencoded.len = calc_base64_encode_len(bufcompressed.len);
		if (wrap_realloc( &body_in, 2*CRLF_LEN + bufencoded.len))
			goto free_mem_full;
		bufencoded.s = body_in.s;

		memcpy(bufencoded.s, CRLF, CRLF_LEN);

		base64encode((unsigned char*)(bufencoded.s + CRLF_LEN),
				(unsigned char*)bufcompressed.s,
							bufcompressed.len);
	} else if (bufcompressed.s) {
		if (wrap_realloc(&body_in, bufcompressed.len + 2*CRLF_LEN))
			goto free_mem_full;

		/* !!! shift buf2compressed CRLF_LEN to the right !!! */
		memcpy(body_in.s+CRLF_LEN, bufcompressed.s, bufcompressed.len);
		memcpy(body_in.s, CRLF, CRLF_LEN);

		bufencoded.len = bufcompressed.len;
		bufencoded.s = body_in.s;
	}

	if (hdr_bufcompressed.s) {

		hdr_bufencoded.len = calc_base64_encode_len(hdr_bufcompressed.len);

		if (wrap_realloc( &hdr_in, hdr_bufencoded.len + CRLF_LEN))
			goto free_mem_full;
		hdr_bufencoded.s = hdr_in.s;

		base64encode((unsigned char*)hdr_bufencoded.s,
				(unsigned char*)hdr_bufcompressed.s,
							hdr_bufcompressed.len);

		wrap_copy_and_update(&hdr_bufencoded.s, CRLF, CRLF_LEN,
							&hdr_bufencoded.len);
	}

	/* Allocate the new buffer */
	int alloc_size;
	str buf2send={NULL, 0};

	alloc_size = msg_start.len + uncompress_len + CRLF_LEN/*the one before all headers*/;

	if (hdr_bufencoded.s) {
		alloc_size += COMP_HDRS_LEN + hdr_bufencoded.len;
		alloc_size += sizeof(HDRS_ENCODING) - 1;
	}

	/* if body compressed new content length and content encoding
	 * plus if required more space for base64 in content encoding header*/

	if (bufencoded.s) {
		alloc_size += CL_NAME_LEN + mc_ndigits(bufencoded.len) + CRLF_LEN;
		alloc_size += CE_NAME_LEN + CRLF_LEN;
		if (flags&B64_ENCODED_FLG) {
			alloc_size += ATTR_DELIM_LEN + (sizeof(BASE64_ALGO)-1);
		}
	}


	switch (algo) {
		case 0: /* deflate*/
			if (bufencoded.s)
				alloc_size += DEFLATE_CE_LEN;
			if (hdr_bufencoded.s)
				alloc_size += sizeof(DEFLATE_ALGO) - 1;
			break;
		case 1: /* gzip */
			if (bufencoded.s)
				alloc_size += GZIP_CE_LEN;
			if (hdr_bufencoded.s)
				alloc_size += sizeof(GZIP_ALGO) - 1;
			break;
		default:
			LM_ERR("compression algo not impelemented\n");
			goto free_mem_full;
	}

	if (bufencoded.s)
		alloc_size += bufencoded.len + CRLF_LEN;
	else
		alloc_size += strlen(buf);

	if (wrap_realloc(&buf_out, alloc_size))
		goto free_mem_full;

	buf2send.s = buf_out.s;

	/* Copy message start */
	wrap_copy_and_update( &buf2send.s, msg_start.s, msg_start.len,
							&buf2send.len);

	/* Copy mandatory headers */
	for (mnd_hdrs = mnd_hdrs_head; mnd_hdrs; mnd_hdrs = mnd_hdrs->next) {
		wrap_copy_and_update( &buf2send.s, mnd_hdrs->name.s,
						mnd_hdrs->len, &buf2send.len);
	}


	if ((flags&BODY_COMP_FLG) && bufencoded.s) {
		wrap_copy_and_update( &buf2send.s, CL_NAME,
						CL_NAME_LEN, &buf2send.len);

		wrap_copy_and_update( &buf2send.s, int2str(bufencoded.len, &len),
					mc_ndigits(bufencoded.len), &buf2send.len);
		wrap_copy_and_update( &buf2send.s, CRLF, CRLF_LEN, &buf2send.len);
	}

	if (hdr_bufencoded.s) {
		wrap_copy_and_update( &buf2send.s, COMP_HDRS, COMP_HDRS_LEN,
								&buf2send.len);

		wrap_copy_and_update( &buf2send.s, hdr_bufencoded.s,
					hdr_bufencoded.len, &buf2send.len);

	}

	switch (algo) {
	case 0: /* deflate */
		if (hdr_bufencoded.s) {
			str hdr_name = str_init(HDRS_ENCODING),
				hdr_value = str_init(DEFLATE_ALGO);
			wrap_copy_and_update(&buf2send.s, hdr_name.s,
						hdr_name.len, &buf2send.len);

			if (flags & B64_ENCODED_FLG) {
				wrap_copy_and_update(&buf2send.s, BASE64_ALGO,
						sizeof(BASE64_ALGO)-1, &buf2send.len);
				wrap_copy_and_update(&buf2send.s, ATTR_DELIM,
						ATTR_DELIM_LEN, &buf2send.len);
			}
			wrap_copy_and_update(&buf2send.s, hdr_value.s,
						hdr_value.len, &buf2send.len);
			wrap_copy_and_update(&buf2send.s, CRLF,
							CRLF_LEN, &buf2send.len);

		}

		if (bufencoded.s) {
			wrap_copy_and_update(&buf2send.s, CE_NAME,
						CE_NAME_LEN, &buf2send.len);

			if (flags & B64_ENCODED_FLG) {
				wrap_copy_and_update(&buf2send.s, BASE64_ALGO,
						sizeof(BASE64_ALGO)-1, &buf2send.len);
				wrap_copy_and_update(&buf2send.s, ATTR_DELIM,
						ATTR_DELIM_LEN, &buf2send.len);
			}
			wrap_copy_and_update(&buf2send.s, DEFLATE_ALGO,
							sizeof(DEFLATE_ALGO)-1, &buf2send.len);
			wrap_copy_and_update(&buf2send.s, CRLF,
							CRLF_LEN, &buf2send.len);
		}
		break;
	case 1: /* gzip */
		if (hdr_bufencoded.s) {
			str hdr_name = str_init(HDRS_ENCODING),
				hdr_value = str_init(GZIP_ALGO);
			if (flags & B64_ENCODED_FLG) {
				wrap_copy_and_update(&buf2send.s, BASE64_ALGO,
						sizeof(BASE64_ALGO)-1, &buf2send.len);
				wrap_copy_and_update(&buf2send.s, ATTR_DELIM,
						ATTR_DELIM_LEN, &buf2send.len);
			}
			wrap_copy_and_update(&buf2send.s, hdr_name.s,
						hdr_name.len, &buf2send.len);
			wrap_copy_and_update(&buf2send.s, hdr_value.s,
						hdr_value.len, &buf2send.len);
			wrap_copy_and_update(&buf2send.s, CRLF,
							CRLF_LEN, &buf2send.len);
		}

		if (bufencoded.s) {
			wrap_copy_and_update(&buf2send.s, CE_NAME,
						CE_NAME_LEN, &buf2send.len);
			if (flags & B64_ENCODED_FLG) {
				wrap_copy_and_update(&buf2send.s, BASE64_ALGO,
						sizeof(BASE64_ALGO)-1, &buf2send.len);
				wrap_copy_and_update(&buf2send.s, ATTR_DELIM,
						ATTR_DELIM_LEN, &buf2send.len);
			}
			wrap_copy_and_update(&buf2send.s, GZIP_ALGO,
							sizeof(GZIP_ALGO)-1, &buf2send.len);
			wrap_copy_and_update(&buf2send.s, CRLF,
							CRLF_LEN, &buf2send.len);
		}
		break;
	default:
		LM_ERR("compression algo not impelemented\n");
		goto free_mem_full;
	}


	/* Copy message body */
	if (bufencoded.s) {
		wrap_copy_and_update( &buf2send.s, bufencoded.s,
					bufencoded.len+CRLF_LEN, &buf2send.len);

		wrap_copy_and_update( &buf2send.s, CRLF,
						CRLF_LEN, &buf2send.len);
	} else {
		wrap_copy_and_update( &buf2send.s, buf, strlen(buf),
							&buf2send.len);
	}

	switch (type) {
		case TM_CB:
			shm_free(*buf_p);
			*buf_p = shm_malloc(buf2send.len+1);
			if (*buf_p == NULL) {
				LM_ERR("no more sh mem\n");
				goto free_mem_full;
			}
			break;
		case PROCESSING_CB:
			*buf_p = pkg_malloc(buf2send.len+1);
			if (*buf_p == NULL) {
				LM_ERR("no more pkg mem\n");
				goto free_mem_full;
			}
			break;
		default:
			LM_ERR("invalid type\n");
			goto free_mem_full;
	}

	memcpy(*buf_p, buf2send.s, buf2send.len);
	(*buf_p)[buf2send.len] = '\0';
	*olen = buf2send.len;

	free_hdr_list(&mnd_hdrs_head);
	free_hdr_list(&non_mnd_hdrs_head);

	if (wh_param && wh_param->type == WH_TYPE_PVS)
		free_whitelist(&hdr2compress_list);

	return 0;

free_mem_full:
	free_hdr_list(&mnd_hdrs_head);
	free_hdr_list(&non_mnd_hdrs_head);
	if (wh_param && wh_param->type == WH_TYPE_PVS)
		free_whitelist(&hdr2compress_list);

	return -1;
}