/*	map coding auc service file			*/
/*	written by Liu Zhiguo 2002-06-03	*/
/*	Version 2.0							*/
/*	--------------------------------	*/

#include "map_includes.h"

/*	+++++++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding security triplets argument	*/
/*	+++++++++++++++++++++++++++++++++++++++++++++	*/
int assign_securityTriplets_arg(struct MapST_Arg *ptr,u8 *buf, u8 version)
{
	ASN_BUF		asn_buf;
	int			buf_len=0;
	int			temp_len;
	u8			temp_buf[256];
	u8			tag1 = 1;
	char			tlv1[8];
	
	asn_encode(buf,&asn_buf);
	
	sprintf(tlv1, "4-%d", tag1++);
	if(ptr->param_flag & 0x01)		//imsi
		buf_len = add_tlv(tlv1,IMSI_LEN,ptr->imsi,0x00,&asn_buf);
	else
		return RER;
	sprintf(tlv1, "4-%d", tag1++);
	if(ptr->param_flag & 0x02)		//hlr_id
		buf_len = add_tlv(tlv1,HLRID_LEN,ptr->hlr_id,0x00,&asn_buf);
/*	sprintf(tlv1, "1-%d", tag1++);
	if(ptr->param_flag & 0x04)
		buf_len = add_tlv(tlv1, 1, (u8*)&ptr->choice_flag, 0x80, &asn_buf);*/

	//quintuplet		add by gxchen
	if(version == 3)
	{
		sprintf(tlv1, "2-%d", tag1++);
		if(ptr->param_flag & 0x04)
			buf_len = add_tlv(tlv1, 1, &ptr->num_req_vec, 0x00, &asn_buf);
		else
		{
			mapp_log_debug("version_4 assign security arg lack numberOfRequestedVectors");
//			return RER;	//temp take out
		}
		sprintf(tlv1, "5-%d", tag1++);
		if(ptr->param_flag & 0x08)
			buf_len = add_tlv(tlv1, 1, &ptr->seg_prohibit, 0x00, &asn_buf);
		sprintf(tlv1, "1-%d", tag1++);
		if(ptr->param_flag & 0x10)
			buf_len = add_tlv(tlv1, 1, &ptr->imm_res_prefer, 0x80, &asn_buf);
		sprintf(tlv1, "16");
		if(ptr->param_flag & 0x20)
		{
			temp_len = assign_authReSynInfo(&ptr->resyn_info, temp_buf);
			if(temp_len != RER)
				buf_len = add_tlv(tlv1, temp_len, temp_buf, 0x20, &asn_buf);
		}
		sprintf(tlv1, "3-%d", tag1++);
		if(ptr->param_flag & 0x40)
			buf_len = add_tlv(tlv1, 1, (u8*)&ptr->node_type, 0x80, &asn_buf);
		sprintf(tlv1, "4-%d", tag1++);
		if(ptr->param_flag & 0x80)
			buf_len = add_tlv(tlv1, 3, ptr->req_plmn_id, 0x80, &asn_buf);
		sprintf(tlv1, "5-%d", tag1++);
		if(ptr->param_flag & 0x100)
			buf_len = add_tlv(tlv1, 1, &ptr->num_req_add_vec, 0x80, &asn_buf);
		sprintf(tlv1, "6-%d", tag1++);
		if(ptr->param_flag & 0x200)
			buf_len = add_tlv(tlv1, 1, &ptr->add_vec_eps, 0x80, &asn_buf);
	}
	
	return buf_len;
}

int extract_securityTriplets_arg(struct MapST_Arg *ptr,u32 buf_len,u8 *buf, u8 version)
{
	ASN_BUF	asn_buf;
	u8		temp_buf[256];
	int 	len;
	u8		tag1 = 1;
	char		tlv1[8];
		
	if (buf_len == 0)
	{
		mapp_log_debug("MAPP--extract_securityTriplets_arg buf_len=0");
		return RER;
	}
	if(asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;
	ptr->param_flag = 0;
	
	sprintf(tlv1, "4-%d", tag1++);
	len = get_tlv(tlv1,temp_buf,&asn_buf);
	if(len == IMSI_LEN && (temp_buf[IMSI_LEN-1]&0xf0) == 0xf0 )	//imsi
	{
		ptr->param_flag |= 0x01;
		memcpy(ptr->imsi,temp_buf,len);
	}
	else
	{
		mapp_log_debug("%s: lack IMSI", __FUNCTION__);
		return RER;
	}
	sprintf(tlv1, "4-%d", tag1++);
	if((len=get_tlv(tlv1,temp_buf,&asn_buf)) == HLRID_LEN )	//hlr_id
	{
		ptr->param_flag |= 0x02;
		memcpy(ptr->hlr_id,temp_buf,len);
	}
/*	sprintf(tlv1, "1-%d", tag1++);
	if((get_tlv(tlv1, temp_buf, &asn_buf)) == 1)	//choice_flag
	{
		ptr->param_flag |= 0x04;
		ptr->choice_flag = temp_buf[0];
	}*/

	//quintuplet		add by gxchen
	if(version == 3)
	{
		sprintf(tlv1, "2-%d", tag1++);
		if(get_tlv(tlv1, temp_buf, &asn_buf) == 1)
		{
			ptr->param_flag |= 0x04;
			ptr->num_req_vec = temp_buf[0];
		}
		else
		{
			mapp_log_debug("%s: lack numberOfRequestedVectors", __FUNCTION__);
//			return RER;	//temp take out
		}
		sprintf(tlv1, "5-%d", tag1++);
		if(get_tlv(tlv1, temp_buf, &asn_buf) == 1)
		{
			ptr->param_flag |= 0x08;
			ptr->seg_prohibit = temp_buf[0];
		}
		sprintf(tlv1, "1-%d", tag1++);
		if(get_tlv(tlv1, temp_buf, &asn_buf) == 1)
		{
			ptr->param_flag |= 0x10;
			ptr->imm_res_prefer = temp_buf[0];
		}
		sprintf(tlv1, "16");
		if((len = get_tlv(tlv1, temp_buf, &asn_buf)) > 0)
		{
			ptr->param_flag |= 0x20;
			extract_authReSynInfo(&ptr->resyn_info, len, temp_buf);
		}
		sprintf(tlv1, "3-%d", tag1++);
		if(get_tlv(tlv1, temp_buf, &asn_buf) == 1)
		{
			ptr->param_flag |= 0x40;
			ptr->node_type = temp_buf[0];
		}
		sprintf(tlv1, "4-%d", tag1++);
		if(get_tlv(tlv1, temp_buf, &asn_buf) > 0)
		{
			ptr->param_flag |= 0x80;
			memcpy(ptr->req_plmn_id, temp_buf, 3);
		}
		sprintf(tlv1, "5-%d", tag1++);
		if(get_tlv(tlv1, temp_buf, &asn_buf) == 1)
		{
			ptr->param_flag |= 0x100;
			ptr->num_req_add_vec = temp_buf[0];
		}
		sprintf(tlv1, "6-%d", tag1++);
		if(get_tlv(tlv1, temp_buf, &asn_buf) == 1)
		{
			ptr->param_flag |= 0x200;
			ptr->add_vec_eps = temp_buf[0];
		}
	}
	
	return ROK;
}

/*	+++++++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding security triplets response	*/
/*	+++++++++++++++++++++++++++++++++++++++++++++	*/
int assign_securityTriplets_res(struct MapST_Res *ptr,u8 *buf)
{
	ASN_BUF		asn_buf;
	int			buf_len=0;
	int			ii;
	char		tlv1[32];
	int			temp_len;
	u8			temp_buf[256];
	
	asn_encode(buf,&asn_buf);
	if ((ptr->param_flag & 0x2) == 0)
	{
		mapp_log_debug("MAPP--assign_securityTriplets_res flag=0");
		return RER;
	}
	if(ptr->param_flag & 0x01)
		buf_len = add_tlv("1", 1, (u8*)&ptr->choice_flag, 0x80, &asn_buf);
	
	if(ptr->choice_flag == AUTH_LIST_QUINTUPLET)		//add by gxchen
	{
		if (ptr->choice.quin_list.quin_len > AUTHLIST_LEN)
		{
			mapp_log_debug("MAPP--assign_securityTriplets_res quintuplet auth_len>AUTHLIST_LEN");
			return RER;
		}
		for(ii = 0; ii < ptr->choice.quin_list.quin_len && ii < 1; ii ++)
		{
			temp_len = assign_quintuplet(&ptr->choice.quin_list.quintuplet[ii], temp_buf);
			if(temp_len == RER)
				break;
			sprintf(tlv1, "16-%d", ii+1);
			buf_len = add_tlv(tlv1, temp_len, temp_buf, 0x20, &asn_buf);
		}
	}
	else
	{
		if (ptr->choice.tri_list.tri_len > AUTHLIST_LEN)
		{
			mapp_log_debug("MAPP--assign_securityTriplets_res auth_len>AUTHLIST_LEN");
			return RER;
		}
		for (ii = 0;ii < ptr->choice.tri_list.tri_len;ii ++)
		{
			temp_len = assign_authset((AuthSet_struct*)&ptr->choice.tri_list.triplet[ii],temp_buf);
			if (temp_len == RER)
				break;
			sprintf(tlv1,"16-%d",ii+1);
			buf_len = add_tlv(tlv1,temp_len,temp_buf,0x20,&asn_buf);
		}
	}
	
	return buf_len;
}

int extract_securityTriplets_res(struct MapST_Res *ptr,u32 buf_len,u8 *buf)
{
	u8			temp_buf[256];
	char		tlv1[32];
	int			ii;
	int			len;
	ASN_BUF		asn_buf;
	
	if (buf_len == 0)
	{
		mapp_log_debug("MAPP--extract_securityTriplets_res buf_len=0");
		return ROK;
	}
	if(asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;	
	ptr->param_flag = 0;

	//add by gxchen
	if((get_tlv("1", temp_buf, &asn_buf)) == 1)	//choice flag
	{
		ptr->param_flag |= 0x01;
		ptr->choice_flag = temp_buf[0];
	}
	if(ptr->choice_flag == AUTH_LIST_QUINTUPLET)		//quintuplet
	{
		ptr->choice.quin_list.quin_len = 0;
		for(ii = 0; ii < AUTHLIST_LEN; ii++)
		{
			sprintf(tlv1, "16-%d", ii+1);
			len = get_tlv(tlv1, temp_buf, &asn_buf);
			if(len <= 0)	//has not data
				break;
			if(!extract_quintuplet(&ptr->choice.quin_list.quintuplet[ii], len, temp_buf))
				break;
			ptr->param_flag |= 0x02;
			ptr->choice.quin_list.quin_len++;
		}
	}
	else
	{
		ptr->choice.tri_list.tri_len = 0;
		for(ii = 0;ii < AUTHLIST_LEN;ii ++)
		{
			sprintf(tlv1,"16-%d",ii+1);
			len = get_tlv(tlv1,temp_buf,&asn_buf);
			if (len == -1)
				break;
			if (!extract_authset((AuthSet_struct*)&ptr->choice.tri_list.triplet[ii],len,temp_buf))
				break;
			ptr->param_flag |= 0x02;
			ptr->choice.tri_list.tri_len++;
		}
	}
	
	return ROK;
}

/*	++++++++++++++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding interrogation subscriber argument		*/
/*	++++++++++++++++++++++++++++++++++++++++++++++++++++	*/
int assign_interrogateSubscriber_arg(struct MapIS_Arg *ptr,u8 *buf)
{
	ASN_BUF		asn_buf;
	int			buf_len=0;
	u32			flag;

	flag = ptr->param_flag;
	asn_encode(buf,&asn_buf);
	if(flag & 0x01)		//imsi
		buf_len = add_tlv("4-1",IMSI_LEN,ptr->imsi,0x00,&asn_buf);
	else
		return RER;
	if(flag & 0x02)		//hlr_id
		buf_len = add_tlv("4-2",HLRID_LEN,ptr->hlr_id,0x00,&asn_buf);
	return buf_len;	
}

int extract_interrogateSubscriber_arg(struct MapIS_Arg *ptr,u32 buf_len,u8 *buf)
{
	ASN_BUF	asn_buf;
	u8		temp_buf[256];
	int 	len;

	if (buf_len == 0)
	{
		mapp_log_debug("MAPP--extract_interrogateSubscriber_arg buf_len=0");
		return RER;
	}
	if(asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;		
	ptr->param_flag = 0;
	len = get_tlv("4-1",temp_buf,&asn_buf);
	if(len == IMSI_LEN && (temp_buf[IMSI_LEN-1]&0xf0) == 0xf0 )//imsi
	{
		ptr->param_flag|=0x01;
		memcpy(ptr->imsi,temp_buf,len);
	}
	else
		return RER;
	if((get_tlv("4-2",temp_buf,&asn_buf)) == HLRID_LEN)//hlr_id
	{
		ptr->param_flag |= 0x02;
		memcpy(ptr->hlr_id,temp_buf,HLRID_LEN);
	}
	return ROK;		
}

/*	++++++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding create subscriber argument	*/
/*	++++++++++++++++++++++++++++++++++++++++++++	*/
int assign_createSubscriber_arg(struct MapCS_Arg *ptr,u8 *buf)
{
	ASN_BUF		asn_buf;
	int			buf_len=0;
	u32			flag;

	flag = ptr->param_flag;
	asn_encode(buf,&asn_buf);
	if(flag & 0x01)		//imsi
		buf_len = add_tlv("4-1",IMSI_LEN,ptr->imsi,0x00,&asn_buf);
	else
		return RER;
	if(flag & 0x02)		//hlr_id
		buf_len = add_tlv("4-2",HLRID_LEN,ptr->hlr_id,0x00,&asn_buf);
	return buf_len;
}

int extract_createSubscriber_arg(struct MapCS_Arg *ptr,u32 buf_len,u8 *buf)
{
	ASN_BUF	asn_buf;
	u8		temp_buf[256];
	int 	len;

	if (buf_len == 0)
	{
		mapp_log_debug("MAPP--extract_createSubscriber_arg buf_len=0");
		return RER;
	}
	if(asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;
	ptr->param_flag = 0;
	len = get_tlv("4-1",temp_buf,&asn_buf);
	if(len == IMSI_LEN && (temp_buf[7]&0xf0) == 0xf0)	//imsi
	{
		ptr->param_flag |= 0x01;
		memcpy(ptr->imsi,temp_buf,len);
	}
	if((get_tlv("4-2",temp_buf,&asn_buf))==HLRID_LEN)	//hlr_id
	{
		ptr->param_flag |= 0x02;
		memcpy(ptr->hlr_id,temp_buf,HLRID_LEN);
	}
	return ROK;
}

/*	++++++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding delete subscriber argument	*/
/*	++++++++++++++++++++++++++++++++++++++++++++	*/
int assign_deleteSubscriber_arg(struct MapDS_Arg *ptr,u8 *buf)
{
	ASN_BUF		asn_buf;
	int			buf_len=0;
	u32			flag;
	
	flag = ptr->param_flag;
	asn_encode(buf,&asn_buf);
	if(flag & 0x01)		//imsi
		buf_len = add_tlv("4-1",IMSI_LEN,ptr->imsi,0x00,&asn_buf);
	else
		return RER;
	if(flag & 0x02)		//hlr_id
		buf_len = add_tlv("4-2",HLRID_LEN,ptr->hlr_id,0x00,&asn_buf);
	return buf_len;
}

int extract_deleteSubscriber_arg(struct MapDS_Arg *ptr,u32 buf_len,u8 *buf)
{
	ASN_BUF	asn_buf;
	u8		temp_buf[256];
	int 	len;

	if (buf_len == 0)
	{
		mapp_log_debug("MAPP--extract_createSubscriber_arg buf_len=0");
		return RER;
	}
	if(asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;
	ptr->param_flag = 0;
	len = get_tlv("4-1",temp_buf,&asn_buf);
	if(len == IMSI_LEN && (temp_buf[7]&0xf0) == 0xf0)	//imsi
	{
		ptr->param_flag |= 0x01;
		memcpy(ptr->imsi,temp_buf,len);
	}
	if((get_tlv("4-2",temp_buf,&asn_buf))==HLRID_LEN)	//hlr_id
	{
		ptr->param_flag |= 0x02;
		memcpy(ptr->hlr_id,temp_buf,HLRID_LEN);
	}
	return ROK;
}
