Пример #1
0
static int w_crypto_aes_decrypt(sip_msg_t* msg, char* inb, char* keyb, char* outb)
{
	str ins;
	str keys;
	pv_spec_t *dst;
	pv_value_t val;
	EVP_CIPHER_CTX *de=NULL;
	str etext;

	if (fixup_get_svalue(msg, (gparam_t*)inb, &ins) != 0) {
		LM_ERR("cannot get input value\n");
		return -1;
	}
	if (fixup_get_svalue(msg, (gparam_t*)keyb, &keys) != 0) {
		LM_ERR("cannot get key value\n");
		return -1;
	}
	de = EVP_CIPHER_CTX_new();
	if(de==NULL) {
		LM_ERR("cannot get new cipher context\n");
		return -1;
	}
	dst = (pv_spec_t*)outb;

	/* gen key and iv. init the cipher ctx object */
	if (crypto_aes_init((unsigned char *)keys.s, keys.len,
				(unsigned char*)((_crypto_salt_param)?_crypto_salt:0), NULL, de)) {
		EVP_CIPHER_CTX_free(de);
		LM_ERR("couldn't initialize AES cipher\n");
		return -1;
	}

	memset(&val, 0, sizeof(pv_value_t));
	etext.s = pv_get_buffer();
	etext.len = base64_dec((unsigned char *)ins.s, ins.len,
					(unsigned char *)etext.s, pv_get_buffer_size()-1);
	if (etext.len < 0) {
		EVP_CIPHER_CTX_free(de);
		LM_ERR("base64 inpuy with encrypted value is too large (need %d)\n",
				-etext.len);
		return -1;
	}
	val.rs.len = etext.len;
	val.rs.s = (char *)crypto_aes_decrypt(de, (unsigned char *)etext.s,
			&val.rs.len);
	if(val.rs.s==NULL) {
		EVP_CIPHER_CTX_free(de);
		LM_ERR("AES decryption failed\n");
		return -1;
	}
	LM_DBG("plain result: [%.*s]\n", val.rs.len, val.rs.s);
	val.flags = PV_VAL_STR;
	dst->setf(msg, &dst->pvp, (int)EQ_T, &val);

	free(val.rs.s);
	EVP_CIPHER_CTX_cleanup(de);
	EVP_CIPHER_CTX_free(de);
	return 1;
}
Пример #2
0
int pv_get_dlg_variable(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
{

	dlg_cell_t *dlg;
	str * value;
	str spv;

	if (param==NULL || param->pvn.type!=PV_NAME_INTSTR
			|| param->pvn.u.isname.type!=AVP_NAME_STR
			|| param->pvn.u.isname.name.s.s==NULL) {
		LM_CRIT("BUG - bad parameters\n");
		return -1;
	}

	/* Retrieve the dialog for current message */
	dlg=dlg_get_msg_dialog( msg);

	if (dlg) {
		/* Lock the dialog */
		dlg_lock(d_table, &(d_table->entries[dlg->h_entry]));
	} else {
		/* Verify the local list */
		get_local_varlist_pointer(msg, 0);
	}

	/* dcm: todo - the value should be cloned for safe usage */
	value = get_dlg_variable_unsafe(dlg, &param->pvn.u.isname.name.s);

	spv.s = NULL;
	if(value) {
		spv.len = pv_get_buffer_size();
		if(spv.len<value->len+1) {
			LM_ERR("pv buffer too small (%d) - needed %d\n", spv.len, value->len);
		} else {
			spv.s = pv_get_buffer();
			strncpy(spv.s, value->s, value->len);
			spv.len = value->len;
			spv.s[spv.len] = '\0';
		}
	}

	print_lists(dlg);

	/* unlock dialog */
	if (dlg) {
		dlg_unlock(d_table, &(d_table->entries[dlg->h_entry]));
		dlg_release(dlg);
	}

	if (spv.s)
		return pv_get_strval(msg, param, res, &spv);


	return pv_get_null(msg, param, res);
}
Пример #3
0
static int w_crypto_aes_encrypt(sip_msg_t* msg, char* inb, char* keyb, char* outb)
{
	str ins;
	str keys;
	pv_spec_t *dst;
	pv_value_t val;
	EVP_CIPHER_CTX en;
	str etext;

	if (fixup_get_svalue(msg, (gparam_t*)inb, &ins) != 0) {
		LM_ERR("cannot get input value\n");
		return -1;
	}
	if (fixup_get_svalue(msg, (gparam_t*)keyb, &keys) != 0) {
		LM_ERR("cannot get key value\n");
		return -1;
	}
	dst = (pv_spec_t*)outb;

	/* gen key and iv. init the cipher ctx object */
	if (crypto_aes_init((unsigned char *)keys.s, keys.len,
				(unsigned char*)((_crypto_salt_param)?_crypto_salt:0), &en, NULL)) {
		LM_ERR("couldn't initialize AES cipher\n");
		return -1;
	}
	etext.len = ins.len;
	etext.s = (char *)crypto_aes_encrypt(&en, (unsigned char *)ins.s, &etext.len);
	if(etext.s==NULL) {
		LM_ERR("AES encryption failed\n");
		return -1;
	}

	memset(&val, 0, sizeof(pv_value_t));
	val.rs.s = pv_get_buffer();
	val.rs.len = base64_enc((unsigned char *)etext.s, etext.len,
					(unsigned char *)val.rs.s, pv_get_buffer_size()-1);
	if (val.rs.len < 0) {
		LM_ERR("base64 output of encrypted value is too large (need %d)\n",
				-val.rs.len);
		goto error;
	}
	LM_DBG("base64 encrypted result: [%.*s]\n", val.rs.len, val.rs.s);
	val.flags = PV_VAL_STR;
	dst->setf(msg, &dst->pvp, (int)EQ_T, &val);

	free(etext.s);
	EVP_CIPHER_CTX_cleanup(&en);
	return 1;

error:
	free(etext.s);
	EVP_CIPHER_CTX_cleanup(&en);
	return -1;
}
Пример #4
0
static int ki_xavp_params_implode(sip_msg_t *msg, str *sxname, str *svname)
{
	pv_spec_t *vspec=NULL;
	pv_value_t val;

	if(sxname==NULL || sxname->s==NULL || sxname->len<=0) {
		LM_ERR("invalid xavp name\n");
		return -1;
	}
	if(svname==NULL || svname->s==NULL || svname->len<=0) {
		LM_ERR("invalid output var name\n");
		return -1;
	}

	vspec = pv_cache_get(svname);
	if(vspec==NULL) {
		LM_ERR("cannot get pv spec for [%.*s]\n", svname->len, svname->s);
		return -1;
	}
	if(vspec->setf==NULL) {
		LM_ERR("read only output variable [%.*s]\n", svname->len, svname->s);
		return -1;
	}

	val.rs.s = pv_get_buffer();
	val.rs.len = xavp_serialize_fields(sxname, val.rs.s, pv_get_buffer_size());
	if(val.rs.len<=0) {
		return -1;
	}

	val.flags = PV_VAL_STR;
	if(vspec->setf(msg, &vspec->pvp, EQ_T, &val)<0) {
		LM_ERR("setting PV failed [%.*s]\n", svname->len, svname->s);
		return -1;
	}

	return 1;
}
Пример #5
0
int pv_get_xavp(struct sip_msg *msg, pv_param_t *param,
		pv_value_t *res)
{
	pv_xavp_name_t *xname=NULL;
	sr_xavp_t *avp=NULL;
	int idxf = 0;
	int idx = 0;
	int count;
	char *p, *p_ini;
	int p_size;

	if(param==NULL)
	{
		LM_ERR("bad parameters\n");
		return -1;
	}
	xname = (pv_xavp_name_t*)param->pvn.u.dname;

	if(xname->index.type==PVT_EXTRA)
	{
		/* get the index */
		if(pv_get_spec_index(msg, &xname->index.pvp, &idx, &idxf)!=0)
		{
			LM_ERR("invalid index\n");
			return -1;
		}
	}
	/* fix the index */
	if(idx<0)
	{
		count = xavp_count(&xname->name, NULL);
		idx = count + idx;
	}
	avp = xavp_get_by_index(&xname->name, idx, NULL);
	if(avp==NULL)
		return pv_get_null(msg, param, res);
	if(xname->next==NULL)
		return pv_xavp_get_value(msg, param, res, avp);
	if(avp->val.type != SR_XTYPE_XAVP)
		return pv_get_null(msg, param, res);

	idx = 0;
	idxf = 0;
	if(xname->next->index.type==PVT_EXTRA)
	{
		/* get the index */
		if(pv_get_spec_index(msg, &xname->next->index.pvp, &idx, &idxf)!=0)
		{
			LM_ERR("invalid index\n");
			return -1;
		}
	}
	/* fix the index */
	if(idx<0)
	{
		count = xavp_count(&xname->next->name, &avp->val.v.xavp);
		idx = count + idx;
	}
	avp = xavp_get_by_index(&xname->next->name, idx, &avp->val.v.xavp);
	if(avp==NULL)
		return pv_get_null(msg, param, res);
	/* get all values of second key */
	if(idxf==PV_IDX_ALL)
	{
		p_ini = pv_get_buffer();
		p = p_ini;
		p_size = pv_get_buffer_size();
		do {
			if(p!=p_ini)
			{
				if(p-p_ini+PV_FIELD_DELIM_LEN+1>p_size)
				{
					LM_ERR("local buffer length exceeded\n");
					return pv_get_null(msg, param, res);
				}
				memcpy(p, PV_FIELD_DELIM, PV_FIELD_DELIM_LEN);
				p += PV_FIELD_DELIM_LEN;
			}
			if(pv_xavp_get_value(msg, param, res, avp)<0)
			{
				LM_ERR("can get value\n");
				return pv_get_null(msg, param, res);
			}
			if(p-p_ini+res->rs.len+1>p_size)
			{
				LM_ERR("local buffer length exceeded!\n");
				return pv_get_null(msg, param, res);
			}
			memcpy(p, res->rs.s, res->rs.len);
			p += res->rs.len;
		} while ((avp=xavp_get_next(avp))!=0);
		res->rs.s = p_ini;
		res->rs.len = p - p_ini;
		return 0;
	}
	return pv_xavp_get_value(msg, param, res, avp);
}
Пример #6
0
/** Get the function parameter value as string or/and integer (if possible).
 *  @return  0 - Success
 *          -1 - Cannot get value
 */
int get_is_fparam(int* i_dst, str* s_dst, struct sip_msg* msg, fparam_t* param, unsigned int *flags)
{
	int_str val;
	int ret;
	avp_t* avp;
	str tmp;
	pv_value_t pv_val;

	*flags = 0;
	switch(param->type) {
		case FPARAM_INT:
			*i_dst = param->v.i;
			*flags |= PARAM_INT;
			return 0;
		case FPARAM_REGEX:
		case FPARAM_UNSPEC:
		case FPARAM_STRING:
			s_dst->s = param->v.asciiz;
			s_dst->len = strlen(param->v.asciiz);
			*flags |= PARAM_STR;
			break;
		case FPARAM_STR:
			*s_dst = param->v.str;
			*flags |= PARAM_STR;
			break;
		case FPARAM_AVP:
			avp = search_first_avp(param->v.avp.flags, param->v.avp.name,
									&val, 0);
			if (unlikely(!avp)) {
				LM_DBG("Could not find AVP from function parameter '%s'\n",
						param->orig);
				return -1;
			}
			if (avp->flags & AVP_VAL_STR) {
				*s_dst = val.s;
				*flags |= PARAM_STR;
				if (str2int(&val.s, (unsigned int*)i_dst) < 0) {
					LM_ERR("Could not convert AVP string value to int\n");
					return -1;
				}
			} else {
				*i_dst = val.n;
				*flags |= PARAM_INT;
			}
			break;
		case FPARAM_SELECT:
			ret = run_select(&tmp, param->v.select, msg);
			if (unlikely(ret < 0 || ret > 0)) return -1;
			if (unlikely(str2int(&tmp, (unsigned int*)i_dst) < 0)) {
				LM_ERR("Could not convert select result to int\n");
				return -1;
			}
			*flags |= PARAM_INT;
			break;
		case FPARAM_PVS:
			if (likely(pv_get_spec_value(msg, param->v.pvs, &pv_val)==0)) {
				if ((pv_val.flags&(PV_VAL_NULL|PV_VAL_INT))==PV_VAL_INT){
					*i_dst=pv_val.ri;
					*flags |= PARAM_INT;
				}
				if ((pv_val.flags&(PV_VAL_NULL|PV_VAL_STR))==PV_VAL_STR){
					*s_dst=pv_val.rs;
					*flags |= PARAM_STR;
				}
			}else{
				LM_ERR("Could not get PV\n");
				return -1;
			}
			break;
		case FPARAM_PVE:
			s_dst->s=pv_get_buffer();
			s_dst->len=pv_get_buffer_size();
			if (unlikely(pv_printf(msg, param->v.pve, s_dst->s, &s_dst->len)!=0)){
				LM_ERR("Could not convert the PV-formated string to str\n");
				s_dst->len=0;
				return -1;
			}
			*flags |= PARAM_STR;
			break;
	}

	/* Let's convert to int, if possible */
	if (!(*flags & PARAM_INT) && (*flags & PARAM_STR) && str2sint(s_dst, i_dst) == 0)
		*flags |= PARAM_INT;

	if (!*flags) return -1;

	return 0;
}
Пример #7
0
/** Get the function parameter value as string.
 *  @return  0 - Success
 *          -1 - Cannot get value
 */
int get_str_fparam(str* dst, struct sip_msg* msg, fparam_t* param)
{
	int_str val;
	int ret;
	avp_t* avp;
	pv_value_t pv_val;

	switch(param->type) {
		case FPARAM_REGEX:
		case FPARAM_UNSPEC:
		case FPARAM_INT:
			return -1;
		case FPARAM_STRING:
			dst->s = param->v.asciiz;
			dst->len = strlen(param->v.asciiz);
			break;
		case FPARAM_STR:
			*dst = param->v.str;
			break;
		case FPARAM_AVP:
			avp = search_first_avp(param->v.avp.flags, param->v.avp.name,
									&val, 0);
			if (unlikely(!avp)) {
				LM_DBG("Could not find AVP from function parameter '%s'\n",
						param->orig);
				return -1;
			}
			if (likely(avp->flags & AVP_VAL_STR)) {
				*dst = val.s;
			} else {
				/* The caller does not know of what type the AVP will be so
				 * convert int AVPs into string here
				 */
				dst->s = int2str(val.n, &dst->len);
			}
			break;
		case FPARAM_SELECT:
			ret = run_select(dst, param->v.select, msg);
			if (unlikely(ret < 0 || ret > 0)) return -1;
			break;
		case FPARAM_PVS:
			if (likely((pv_get_spec_value(msg, param->v.pvs, &pv_val)==0) &&
						((pv_val.flags&(PV_VAL_NULL|PV_VAL_STR))==PV_VAL_STR))){
					*dst=pv_val.rs;
			}else{
				LM_ERR("Could not convert PV to str\n");
				return -1;
			}
			break;
		case FPARAM_PVE:
			dst->s=pv_get_buffer();
			dst->len=pv_get_buffer_size();
			if (unlikely(pv_printf(msg, param->v.pve, dst->s, &dst->len)!=0)){
				LM_ERR("Could not convert the PV-formated string to str\n");
				dst->len=0;
				return -1;
			};
			break;
	}
	return 0;
}
Пример #8
0
int pv_printf_s(struct sip_msg* msg, pv_elem_p list, str *s)
{
	s->s = pv_get_buffer();
	s->len = pv_get_buffer_size();
	return pv_printf( msg, list, s->s, &s->len);
}
Пример #9
0
int pv_get_msrp(sip_msg_t *msg,  pv_param_t *param, pv_value_t *res)
{
	msrp_frame_t *mf;
	msrp_hdr_t *hdr;
	str_array_t *sar;
	msrp_uri_t uri;
	str s;
	char *p;

	mf = msrp_get_current_frame();
	if(mf==NULL || param==NULL)
		return -1;

	sar = NULL;
	hdr = NULL;

	switch(param->pvn.u.isname.name.n)
	{
		case 1:
			s.s   = mf->buf.s;
			s.len = mf->buf.len;
			return pv_get_strval(msg, param, res, &s);
		case 2:
			if(mf->mbody.s==NULL)
				return pv_get_null(msg, param, res);
			s.s   = mf->mbody.s;
			s.len = mf->mbody.len;
			return pv_get_strval(msg, param, res, &s);
		case 3:
			if(mf->fline.msgtypeid==MSRP_REQUEST)
				return pv_get_null(msg, param, res);
			return pv_get_intstrval(msg, param, res,
					MSRP_RPL_CODE(mf->fline.rtypeid),
					&mf->fline.rtype);
		case 4:
			if(mf->hbody.s==NULL)
				return pv_get_null(msg, param, res);
			s.s   = mf->hbody.s;
			s.len = mf->hbody.len;
			return pv_get_strval(msg, param, res, &s);
		case 5:
			hdr = msrp_get_hdr_by_id(mf, MSRP_HDR_MESSAGE_ID);
			if(hdr==NULL)
				return pv_get_null(msg, param, res);
			s.s   = hdr->body.s;
			s.len = hdr->body.len;
			trim(&s);
			return pv_get_strval(msg, param, res, &s);
		case 6:
			if(mf->fline.msgtypeid==MSRP_REPLY)
				return pv_get_null(msg, param, res);
			return pv_get_strintval(msg, param, res, &mf->fline.rtype,
					mf->fline.rtypeid);
		case 7:
			return pv_get_uintval(msg, param, res, mf->buf.len);
		case 8:
			if(msrp_parse_hdr_to_path(mf)<0)
				return pv_get_null(msg, param, res);
			hdr = msrp_get_hdr_by_id(mf, MSRP_HDR_TO_PATH);
			if(hdr==NULL)
				return pv_get_null(msg, param, res);
			sar = (str_array_t*)hdr->parsed.data;
			s = sar->list[0];
			trim(&s);
			if(msrp_parse_uri(s.s, s.len, &uri)<0 || uri.session.len<=0)
				return pv_get_null(msg, param, res);
			s = uri.session;
			trim(&s);
			return pv_get_strval(msg, param, res, &s);
		case 9:
			if(mf->fline.msgtypeid==MSRP_REQUEST || mf->fline.rtext.s==NULL)
				return pv_get_null(msg, param, res);
			return pv_get_strval(msg, param, res, &mf->fline.rtext);
		case 10:
			return pv_get_uintval(msg, param, res, mf->mbody.len);
		case 11:
			s = mf->fline.transaction;
			trim(&s);
			return pv_get_strval(msg, param, res, &s);
		case 12:
			if(msrp_parse_hdr_to_path(mf)<0)
				return pv_get_null(msg, param, res);
			hdr = msrp_get_hdr_by_id(mf, MSRP_HDR_TO_PATH);
			if(hdr==NULL)
				return pv_get_null(msg, param, res);
			sar = (str_array_t*)hdr->parsed.data;
			s = sar->list[0];
			trim(&s);
			return pv_get_strval(msg, param, res, &s);
		case 13:
			if(msrp_parse_hdr_from_path(mf)<0)
				return pv_get_null(msg, param, res);
			hdr = msrp_get_hdr_by_id(mf, MSRP_HDR_FROM_PATH);
			if(hdr==NULL)
				return pv_get_null(msg, param, res);
			sar = (str_array_t*)hdr->parsed.data;
			s = sar->list[0];
			trim(&s);
			return pv_get_strval(msg, param, res, &s);
		case 14:
			if(msrp_parse_hdr_to_path(mf)<0)
				return pv_get_null(msg, param, res);
			hdr = msrp_get_hdr_by_id(mf, MSRP_HDR_TO_PATH);
			if(hdr==NULL)
				return pv_get_null(msg, param, res);
			sar = (str_array_t*)hdr->parsed.data;
			if(sar->size<2)
				return pv_get_null(msg, param, res);
			s = sar->list[1];
			trim(&s);
			return pv_get_strval(msg, param, res, &s);
		case 15:
			if(msrp_parse_hdr_to_path(mf)<0)
				return pv_get_null(msg, param, res);
			hdr = msrp_get_hdr_by_id(mf, MSRP_HDR_TO_PATH);
			if(hdr==NULL)
				return pv_get_null(msg, param, res);
			sar = (str_array_t*)hdr->parsed.data;
			s = sar->list[sar->size-1];
			trim(&s);
			return pv_get_strval(msg, param, res, &s);
		case 16:
			if(msrp_parse_hdr_from_path(mf)<0)
				return pv_get_null(msg, param, res);
			hdr = msrp_get_hdr_by_id(mf, MSRP_HDR_FROM_PATH);
			if(hdr==NULL)
				return pv_get_null(msg, param, res);
			sar = (str_array_t*)hdr->parsed.data;
			s = sar->list[sar->size-1];
			trim(&s);
			return pv_get_strval(msg, param, res, &s);
		case 17:
			if(msrp_parse_hdr_from_path(mf)<0)
				return pv_get_null(msg, param, res);
			hdr = msrp_get_hdr_by_id(mf, MSRP_HDR_FROM_PATH);
			if(hdr==NULL)
				return pv_get_null(msg, param, res);
			sar = (str_array_t*)hdr->parsed.data;
			return pv_get_uintval(msg, param, res, sar->size);
		case 18:
			if(msrp_parse_hdr_to_path(mf)<0)
				return pv_get_null(msg, param, res);
			hdr = msrp_get_hdr_by_id(mf, MSRP_HDR_TO_PATH);
			if(hdr==NULL)
				return pv_get_null(msg, param, res);
			sar = (str_array_t*)hdr->parsed.data;
			return pv_get_uintval(msg, param, res, sar->size-1);
		case 19:
			if(pv_get_buffer_size()<100)
				return pv_get_null(msg, param, res);
			s.s = pv_get_buffer();
			p = s.s;
			if(mf->tcpinfo->rcv->proto==PROTO_TLS)
			{
				memcpy(p, "msrps://", 8);
				p+=8;
			} else {
				memcpy(p, "msrp://", 7);
				p+=7;
			}
			strcpy(p, ip_addr2a(&mf->tcpinfo->rcv->src_ip));
			strcat(p, ":");
			strcat(p, int2str(mf->tcpinfo->rcv->src_port, NULL));
			s.len = strlen(s.s);
			return pv_get_strval(msg, param, res, &s);
		case 20:
			return pv_get_strval(msg, param, res,
					&mf->tcpinfo->rcv->bind_address->sock_str);
		case 21:
			if(mf->tcpinfo->con==NULL)
				return pv_get_null(msg, param, res);
			return pv_get_sintval(msg, param, res, mf->tcpinfo->con->id);
		default:
			return pv_get_null(msg, param, res);
	}

	return 0;
}
Пример #10
0
int pv_get_dlg(struct sip_msg *msg, pv_param_t *param,
		pv_value_t *res)
{
	dlg_cell_t *dlg = NULL;
	int res_type = 0;
	str sv = { 0 };
	unsigned int ui = 0;

	if(param==NULL)
		return -1;

	if(_dlg_ctx.iuid.h_id==0)
	{
		/* Retrieve the dialog for current message */
		dlg=dlg_get_msg_dialog(msg);
	} else {
		/* Retrieve the dialog for current context */
		dlg=dlg_get_by_iuid(&_dlg_ctx.iuid);
	}
	if(dlg == NULL)
		return pv_get_null(msg, param, res);

	switch(param->pvn.u.isname.name.n)
	{
		case 1:
			res_type = 1;
			ui = (unsigned int)dlg->h_id;
			break;
		case 2:
			res_type = 1;
			ui = (unsigned int)dlg->state;
			break;
		case 3:
			if(dlg->route_set[DLG_CALLEE_LEG].s==NULL
					|| dlg->route_set[DLG_CALLEE_LEG].len<=0)
				goto done;
			sv.s = pv_get_buffer();
			sv.len = dlg->route_set[DLG_CALLEE_LEG].len;
			if(pv_get_buffer_size()<sv.len)
				goto done;
			res_type = 2;
			strncpy(sv.s, dlg->route_set[DLG_CALLEE_LEG].s, sv.len);
			sv.s[sv.len] = '\0';
			break;
		case 4:
			res_type = 1;
			ui = (unsigned int)dlg->dflags;
			break;
		case 5:
			res_type = 1;
			ui = (unsigned int)dlg->sflags;
			break;
		case 6:
			if(dlg->callid.s==NULL
					|| dlg->callid.len<=0)
				goto done;
			sv.s = pv_get_buffer();
			sv.len = dlg->callid.len;
			if(pv_get_buffer_size()<sv.len)
				goto done;
			res_type = 2;
			strncpy(sv.s, dlg->callid.s, sv.len);
			sv.s[sv.len] = '\0';
			break;
		case 7:
			if(dlg->to_uri.s==NULL
					|| dlg->to_uri.len<=0)
				goto done;
			sv.s = pv_get_buffer();
			sv.len = dlg->to_uri.len;
			if(pv_get_buffer_size()<sv.len)
				goto done;
			res_type = 2;
			strncpy(sv.s, dlg->to_uri.s, sv.len);
			sv.s[sv.len] = '\0';
			break;
		case 8:
			if(dlg->tag[DLG_CALLEE_LEG].s==NULL
					|| dlg->tag[DLG_CALLEE_LEG].len<=0)
				goto done;
			sv.s = pv_get_buffer();
			sv.len = dlg->tag[DLG_CALLEE_LEG].len;
			if(pv_get_buffer_size()<sv.len)
				goto done;
			res_type = 2;
			strncpy(sv.s, dlg->tag[DLG_CALLEE_LEG].s, sv.len);
			sv.s[sv.len] = '\0';
			break;
		case 9:
			res_type = 1;
			ui = (unsigned int)dlg->toroute;
			break;
		case 10:
			if(dlg->cseq[DLG_CALLEE_LEG].s==NULL
					|| dlg->cseq[DLG_CALLEE_LEG].len<=0)
				goto done;
			sv.s = pv_get_buffer();
			sv.len = dlg->cseq[DLG_CALLEE_LEG].len;
			if(pv_get_buffer_size()<sv.len)
				goto done;
			res_type = 2;
			strncpy(sv.s, dlg->cseq[DLG_CALLEE_LEG].s, sv.len);
			sv.s[sv.len] = '\0';
			break;
		case 11:
			if(dlg->route_set[DLG_CALLER_LEG].s==NULL
					|| dlg->route_set[DLG_CALLER_LEG].len<=0)
				goto done;
			sv.s = pv_get_buffer();
			sv.len = dlg->route_set[DLG_CALLER_LEG].len;
			if(pv_get_buffer_size()<sv.len)
				goto done;
			res_type = 2;
			strncpy(sv.s, dlg->route_set[DLG_CALLER_LEG].s, sv.len);
			sv.s[sv.len] = '\0';
			break;
		case 12:
			if(dlg->from_uri.s==NULL
					|| dlg->from_uri.len<=0)
				goto done;
			sv.s = pv_get_buffer();
			sv.len = dlg->from_uri.len;
			if(pv_get_buffer_size()<sv.len)
				goto done;
			res_type = 2;
			strncpy(sv.s, dlg->from_uri.s, sv.len);
			sv.s[sv.len] = '\0';
			break;
		case 13:
			if(dlg->tag[DLG_CALLER_LEG].s==NULL
					|| dlg->tag[DLG_CALLER_LEG].len<=0)
				goto done;
			sv.s = pv_get_buffer();
			sv.len = dlg->tag[DLG_CALLER_LEG].len;
			if(pv_get_buffer_size()<sv.len)
				goto done;
			res_type = 2;
			strncpy(sv.s, dlg->tag[DLG_CALLER_LEG].s, sv.len);
			sv.s[sv.len] = '\0';
			break;
		case 14:
			res_type = 1;
			ui = (unsigned int)dlg->lifetime;
			break;
		case 15:
			res_type = 1;
			ui = (unsigned int)dlg->start_ts;
			break;
		case 16:
			if(dlg->cseq[DLG_CALLER_LEG].s==NULL
					|| dlg->cseq[DLG_CALLER_LEG].len<=0)
				goto done;
			sv.s = pv_get_buffer();
			sv.len = dlg->cseq[DLG_CALLER_LEG].len;
			if(pv_get_buffer_size()<sv.len)
				goto done;
			res_type = 2;
			strncpy(sv.s, dlg->cseq[DLG_CALLER_LEG].s, sv.len);
			sv.s[sv.len] = '\0';
			break;
		case 17:
			if(dlg->contact[DLG_CALLEE_LEG].s==NULL
					|| dlg->contact[DLG_CALLEE_LEG].len<=0)
				goto done;
			sv.s = pv_get_buffer();
			sv.len = dlg->contact[DLG_CALLEE_LEG].len;
			if(pv_get_buffer_size()<sv.len)
				goto done;
			res_type = 2;
			strncpy(sv.s, dlg->contact[DLG_CALLEE_LEG].s, sv.len);
			sv.s[sv.len] = '\0';
			break;
		case 18:
			if(dlg->bind_addr[DLG_CALLEE_LEG]==NULL)
				goto done;
			sv.s = pv_get_buffer();
			sv.len = dlg->bind_addr[DLG_CALLEE_LEG]->sock_str.len;
			if(pv_get_buffer_size()<sv.len)
				goto done;
			res_type = 2;
			strncpy(sv.s, dlg->bind_addr[DLG_CALLEE_LEG]->sock_str.s, sv.len);
			sv.s[sv.len] = '\0';
			break;
		case 19:
			if(dlg->contact[DLG_CALLER_LEG].s==NULL
					|| dlg->contact[DLG_CALLER_LEG].len<=0)
				goto done;
			sv.s = pv_get_buffer();
			sv.len = dlg->contact[DLG_CALLER_LEG].len;
			if(pv_get_buffer_size()<sv.len)
				goto done;
			res_type = 2;
			strncpy(sv.s, dlg->contact[DLG_CALLER_LEG].s, sv.len);
			sv.s[sv.len] = '\0';
			break;
		case 20:
			if(dlg->bind_addr[DLG_CALLER_LEG]==NULL)
				goto done;
			sv.s = pv_get_buffer();
			sv.len = dlg->bind_addr[DLG_CALLER_LEG]->sock_str.len;
			if(pv_get_buffer_size()<sv.len)
				goto done;
			res_type = 2;
			strncpy(sv.s, dlg->bind_addr[DLG_CALLER_LEG]->sock_str.s, sv.len);
			sv.s[sv.len] = '\0';
			break;
		case 21:
			res_type = 1;
			ui = (unsigned int)dlg->h_entry;
			break;
		default:
			res_type = 1;
			ui = (unsigned int)dlg->ref;
	}

done:
	dlg_release(dlg);

	switch(res_type) {
		case 1:
			return pv_get_uintval(msg, param, res, ui);
		case 2:
			return pv_get_strval(msg, param, res, &sv);
		default:
			return pv_get_null(msg, param, res);
	}
}