#include "./include/m2ua_pub.h"
#include "./include/m2ua.h"
#include "./include/m2ua_const.h"
#include "./include/m2ua_struct.h"
#include "./include/m2ua_ext.h"
#include "./include/m2ua_fsm.h"
#include "./include/m2ua_debug.h"
#include "./include/m2ua_msg.h"


#ifndef _LKSCTP

static struct strfdinsert 		m2ua_sctp_fdi = 
{
	{M2UA_SCTP_CMD_BUFSIZE, 0, m2ua_sctp_cmd.cbuf},
	{M2UA_SCTP_DAT_BUFSIZE, 0, m2ua_sctp_dat},
	0,
	0,
	0
};

static m2ua_sctp_opt_data_t		m2ua_sctp_opt_data =
{
	{
		sizeof(struct t_opthdr) + sizeof(t_scalar_t),
		T_INET_SCTP,
		T_SCTP_SID,
		T_SUCCESS
	},
	0
};

m2ua_sctp_opt_optm_t		m2ua_sctp_opt_optm =
{
	{
		sizeof(struct t_opthdr) + sizeof(t_scalar_t),
		T_INET_SCTP,
		T_SCTP_NODELAY,
		T_SUCCESS
	},
	T_YES,
	{
		sizeof(struct t_opthdr) + sizeof(t_scalar_t),
		T_INET_SCTP,
		T_SCTP_CORK,
		T_SUCCESS
	},
	T_YES,
	{
		sizeof(struct t_opthdr) + sizeof(t_scalar_t),
		T_INET_SCTP,
		T_SCTP_PPI,
		T_SUCCESS
	},
	2,
	{
		sizeof(struct t_opthdr) + sizeof(t_scalar_t),
		T_INET_SCTP,
		T_SCTP_SID,
		T_SUCCESS
	},
	0,
	{
		sizeof(struct t_opthdr) + sizeof(t_scalar_t),
		T_INET_SCTP,
		T_SCTP_RECVOPT,
		T_SUCCESS
	},
	T_NO,
	{
		sizeof(struct t_opthdr) + sizeof(t_scalar_t),
		T_INET_SCTP,
		T_SCTP_COOKIE_LIFE,
		T_SUCCESS
	},
	60000,
	{
		sizeof(struct t_opthdr) + sizeof(t_scalar_t),
		T_INET_SCTP,
		T_SCTP_SACK_DELAY,
		T_SUCCESS
	},
	0,
	{
		sizeof(struct t_opthdr) + sizeof(t_scalar_t),
		T_INET_SCTP,
		T_SCTP_PATH_MAX_RETRANS,
		T_SUCCESS
	},
	5,
	{
		sizeof(struct t_opthdr) + sizeof(t_scalar_t),
		T_INET_SCTP,
		T_SCTP_ASSOC_MAX_RETRANS,
		T_SUCCESS
	},
	5,
	{
		sizeof(struct t_opthdr) + sizeof(t_scalar_t),
		T_INET_SCTP,
		T_SCTP_MAX_INIT_RETRIES,
		T_SUCCESS
	},
	8,
	{
		sizeof(struct t_opthdr) + sizeof(t_scalar_t),
		T_INET_SCTP,
		T_SCTP_HEARTBEAT_ITVL,
		T_SUCCESS
	},
	20000,
	{
		sizeof(struct t_opthdr) + sizeof(t_scalar_t),
		T_INET_SCTP,
		T_SCTP_RTO_INITIAL,
		T_SUCCESS
	},
	1000,
	{
		sizeof(struct t_opthdr) + sizeof(t_scalar_t),
		T_INET_SCTP,
		T_SCTP_RTO_MIN,
		T_SUCCESS
	},
	1000,
	{
		sizeof(struct t_opthdr) + sizeof(t_scalar_t),
		T_INET_SCTP,
		T_SCTP_RTO_MAX,
		T_SUCCESS
	},
	5000,
	{
		sizeof(struct t_opthdr) + sizeof(t_scalar_t),
		T_INET_SCTP,
		T_SCTP_OSTREAMS,
		T_SUCCESS
	},
	257,
	{
		sizeof(struct t_opthdr) + sizeof(t_scalar_t),
		T_INET_SCTP,
		T_SCTP_ISTREAMS,
		T_SUCCESS
	},
	257,
	{
		sizeof(struct t_opthdr) + sizeof(t_scalar_t),
		T_INET_SCTP,
		T_SCTP_COOKIE_INC,
		T_SUCCESS
	},
	0,
	{
		sizeof(struct t_opthdr) + sizeof(t_scalar_t),
		T_INET_SCTP,
		T_SCTP_THROTTLE_ITVL,
		T_SUCCESS
	},
	50,
	{
		sizeof(struct t_opthdr) + sizeof(t_scalar_t),
		T_INET_SCTP,
		T_SCTP_MAC_TYPE,
		T_SUCCESS
	},
	SCTP_HMAC_NONE,
	{
		sizeof(struct t_opthdr) + sizeof(t_scalar_t),
		T_INET_SCTP,
		T_SCTP_DEBUG,
		T_SUCCESS
	},
	0
};

#endif
extern int check_m3ua_rc_verify(DWORD rc);

char *dec_m2ua_msg(WORD m2ua_msg)
{
	switch (m2ua_msg)
	{		
		case M2UA_MAUP_DATA:				return("M2UA_MAUP_DATA");
		case M2UA_MAUP_ESTABLISH_REQ:		return("M2UA_MAUP_ESTABLISH_REQ");
		case M2UA_MAUP_ESTABLISH_CFM:		return("M2UA_MAUP_ESTABLISH_CFM");
		case M2UA_MAUP_RELEASE_REQ:			return("M2UA_MAUP_RELEASE_REQ");
		case M2UA_MAUP_RELEASE_CFM:			return("M2UA_MAUP_RELEASE_CFM");
		case M2UA_MAUP_RELEASE_IND:			return("M2UA_MAUP_RELEASE_IND");
		case M2UA_MAUP_STATE_REQ:			return("M2UA_MAUP_STATE_REQ");
		case M2UA_MAUP_STATE_CFM:			return("M2UA_MAUP_STATE_CFM");
		case M2UA_MAUP_STATE_IND:			return("M2UA_MAUP_STATE_IND");
		case M2UA_MAUP_DATA_RETIEVE_REQ:	return("M2UA_MAUP_DATA_RETIEVE_REQ");
		case M2UA_MAUP_DATA_RETIEVE_CFM:	return("M2UA_MAUP_DATA_RETIEVE_CFM");
		case M2UA_MAUP_DATA_RETIEVE_IND:	return("M2UA_MAUP_DATA_RETIEVE_IND");
		case M2UA_MAUP_DATA_RETIEVE_CMP:	return("M2UA_MAUP_DATA_RETIEVE_CMP");
		case M2UA_MAUP_CONGESTION_IND:		return("M2UA_MAUP_CONGESTION_IND");
		case M2UA_MAUP_DATA_ACK:			return("M2UA_MAUP_DATA_ACK");

		case xUA_MGMT_ERROR:				return("xUA_MGMT_ERROR");
		case xUA_MGMT_NOTIFY:				return("xUA_MGMT_NOTIFY");		
		case xUA_MGMT_TEI_S_REQ:				return("xUA_MGMT_TEI_S_REQ");
		case xUA_MGMT_TEI_S_CFM:				return("xUA_MGMT_TEI_S_CFM");
		case xUA_MGMT_TEI_S_IND:				return("xUA_MGMT_TEI_S_IND");
 			
		case xUA_ASPSM_ASP_UP:				return("xUA_ASPSM_ASP_UP");
		case xUA_ASPSM_ASP_DOWN:			return("xUA_ASPSM_ASP_DOWN");
		case xUA_ASPSM_HEARTBEAT:			return("xUA_ASPSM_HEARTBEAT");
		case xUA_ASPSM_ASP_UP_ACK:			return("xUA_ASPSM_ASP_UP_ACK");
		case xUA_ASPSM_ASP_DOWN_ACK:		return("xUA_ASPSM_ASP_DOWN_ACK");
		case xUA_ASPSM_HEARTBEAT_ACK:		return("xUA_ASPSM_HEARTBEAT_ACK");
		
		case xUA_ASPTM_ASP_ACTIVE:			return("xUA_ASPTM_ASP_ACTIVE");
		case xUA_ASPTM_ASP_INACTIVE:		return("xUA_ASPTM_ASP_INACTIVE");
		case xUA_ASPTM_ASP_ACTIVE_ACK:		return("xUA_ASPTM_ASP_ACTIVE_ACK");
		case xUA_ASPTM_ASP_INACTIVE_ACK:	return("xUA_ASPTM_ASP_INACTIVE_ACK");
			
		case IUA_QPTM_DATA_REQ:					return("IUA_QPTM_DATA_REQ");
		case IUA_QPTM_DATA_IND:					return("IUA_QPTM_DATA_IND");
		case IUA_QPTM_UDATA_REQ:					return("IUA_QPTM_UDATA_REQ");
		case IUA_QPTM_UDATA_IND:					return("IUA_QPTM_UDATA_IND");
		case IUA_QPTM_ESTABLISH_REQ:			return("IUA_QPTM_ESTABLISH_REQ");
		case IUA_QPTM_ESTABLISH_CFM:			return("IUA_QPTM_ESTABLISH_CFM");
		case IUA_QPTM_ESTABLISH_IND:			return("IUA_QPTM_ESTABLISH_IND");
		case IUA_QPTM_RELEASE_REQ:				return("IUA_QPTM_RELEASE_REQ");
		case IUA_QPTM_RELEASE_CFM:				return("IUA_QPTM_RELEASE_CFM");
		case IUA_QPTM_RELEASE_IND:				return("IUA_QPTM_RELEASE_IND");			

		case M3UA_MAUP_DATA:							return("M3UA_MAUP_DATA");
				                      			
		case M3UA_SSNM_DUNA:							return("M3UA_SSNM_DUNA");			
		case M3UA_SSNM_DAVA:							return("M3UA_SSNM_DAVA");			
		case M3UA_SSNM_DAUD:							return("M3UA_SSNM_DAUD");
		case M3UA_SSNM_SCON:							return("M3UA_SSNM_SCON");
		case M3UA_SSNM_DUPU:							return("M3UA_SSNM_DUPU");
		case M3UA_SSNM_DRST:							return("M3UA_SSNM_DRST");												
			
		default:													return("Unexpected");
	}
}

int m2ua_make_par(m2ua_var_par_t *par_ptr, WORD par_type, BYTE *par_addr, WORD par_len)
{
	WORD len = 0;
	
	par_ptr->hdr.tag	= htons(par_type);
	par_ptr->hdr.len	= htons(sizeof(m2ua_par_hdr_t) + par_len);
	
	len	= sizeof(m2ua_par_hdr_t) + ((par_len + 3) & 0xFFFC);
	if (par_type == M2UA_PAR_PROTO_DATA_1 ||
			par_type == M3UA_Protocol_Data )
		bzero(par_ptr->val + par_len, len - par_len);
	else	
		bcopy(par_addr, par_ptr->val, par_len);
	
	
	return len;
}

int m2ua_send_msg(WORD sg_id, WORD msg)
{
	BYTE 		msg_class, msg_type;
	WORD		len = 0, msg_len;
	WORD		par_len, par_start = 0;
	WORD		sid = 0, i;
	DWORD		dw;
	BYTE		iid, lk, flag = 0;
	WORD		dlci;
	m2ua_msg_t 	*msg_ptr;
	
	msg_class 	= msg >> 8;
	msg_type 	= msg & 0xFF;

	if (msg == M2UA_MAUP_DATA || msg == M3UA_MAUP_DATA ||
		msg == IUA_QPTM_DATA_REQ || msg == IUA_QPTM_UDATA_REQ  ||
		msg == IUA_QPTM_DATA_IND || msg == IUA_QPTM_UDATA_IND  )
		msg_ptr	= (m2ua_msg_t *)m2ua_sg_info[sg_id].msg;
	else
		//msg_ptr	= (m2ua_msg_t *)m2ua_sctp_dat;
		msg_ptr	= (m2ua_msg_t *)m2ua_sctp_dat_send;
	
	switch (msg_class)
	{
		case M2UA_MCLASS_MGMT:
		{	
			switch (msg_type)
			{
				case xUA_ERROR:
					dw = htonl(m2ua_sg_info[sg_id].err_code);
					par_len = m2ua_make_par((m2ua_var_par_t *) &msg_ptr->msg[par_start],
										M2UA_PAR_ERR_CODE, (BYTE *)&dw, 4); 
					len							+= par_len;
					if(m2ua_sg_info[sg_id].err_code == M3UA_ERR_INVALID_RC)
					{
						par_start 					+= par_len;
						dw = htonl(m2ua_sg_info[sg_id].rc);
						par_len = m2ua_make_par((m2ua_var_par_t *) &msg_ptr->msg[par_start],
									xUA_Routing_Context, (BYTE *)&dw, 4); 
						len		+= par_len;												
					}	
					msg_ptr->comhdr.msg_class 	= M2UA_MCLASS_MGMT;
					msg_ptr->comhdr.msg_type	= msg_type;
					len							+= sizeof(m2ua_comhdr_t);
					break;
				case xUA_NOTIFY:
					dw = htonl(m2ua_sg_info[sg_id].status);
					par_len = m2ua_make_par((m2ua_var_par_t *) &msg_ptr->msg[par_start],
										M2UA_PAR_STATUS, (BYTE *)&dw, 4); 
					len							+= par_len;
					if ((m2ua_para.sg_para[sg_id].xUA_ack>>1) == M3UA_APP)
					{
						par_start 					+= par_len;
						dw = htonl(m2ua_sg_info[sg_id].rc);
						par_len = m2ua_make_par((m2ua_var_par_t *) &msg_ptr->msg[par_start],
									xUA_Routing_Context, (BYTE *)&dw, 4); 
						len		+= par_len;						
					}					
					msg_ptr->comhdr.msg_class 	= M2UA_MCLASS_MGMT;
					msg_ptr->comhdr.msg_type	= msg_type;
					len							+= sizeof(m2ua_comhdr_t);
					break;
				case TEI_S_REQ:	
				case TEI_S_CFM:
				case TEI_S_IND:	
					lk 		= m2ua_sg_info[sg_id].iid & 0xFF;
					iid		= m2ua_para.lk_para[lk].iid;
					msg_len	= m2ua_sg_info[sg_id].msg_len;
					sid		= m2ua_lk_info[lk].sid;
					dw		= htonl(iid);
					par_len = m2ua_make_par((m2ua_var_par_t *) &msg_ptr->msg[par_start],
											M2UA_PAR_INTERFACE_ID_INT, (BYTE *) &dw, 4);
					len		+= par_len;			
					//DLCI
					par_start 	+= par_len;
					dlci		= m2ua_para.lk_para[lk].dlci;			
					dw			= htons(dlci) << 16;
					par_len = m2ua_make_par((m2ua_var_par_t *) &msg_ptr->msg[par_start],
									xUA_PAR_DLCI, (BYTE *) &dw, 4);
					len			+= par_len;												
					if(msg_type != TEI_S_REQ)
					{
						dw			= htonl(m2ua_sg_info[sg_id].tei_state);
						par_start 	+= par_len;
						par_len = m2ua_make_par((m2ua_var_par_t *) &msg_ptr->msg[par_start],
										xUA_PAR_TEI_STATUS, (BYTE *) &dw, 4);
						len			+= par_len;					
					}	
					msg_ptr->comhdr.msg_class 	= M2UA_MCLASS_MGMT;
					msg_ptr->comhdr.msg_type	= msg_type;
					len							+= sizeof(m2ua_comhdr_t);
					break;
				default:
					break;
			}
			break;
		}
		case M2UA_MCLASS_ASPSM:
		{	
			switch (msg_type)
			{
				case ASP_UP:
					dw = host_ip;
					par_len = m2ua_make_par((m2ua_var_par_t *) &msg_ptr->msg[par_start],
										M2UA_PAR_ASP_IDENTIFIER, (BYTE *)&dw, 4); 
					len							+= par_len;

					msg_ptr->comhdr.msg_class 	= M2UA_MCLASS_ASPSM;
					msg_ptr->comhdr.msg_type	= ASP_UP;
					len							+= sizeof(m2ua_comhdr_t);
					break;
				case ASP_DOWN:
					break;
				case HEARTBEAT:
					break;
				case ASP_UP_ACK:
					msg_ptr->comhdr.msg_class 	= M2UA_MCLASS_ASPSM;
					msg_ptr->comhdr.msg_type	= ASP_UP_ACK;
					len							+= sizeof(m2ua_comhdr_t);
					break;
				case ASP_DOWN_ACK:
					msg_ptr->comhdr.msg_class 	= M2UA_MCLASS_ASPSM;
					msg_ptr->comhdr.msg_type	= ASP_DOWN_ACK;
					len							+= sizeof(m2ua_comhdr_t);
					break;
				case HEARTBEAT_ACK:
					msg_ptr->comhdr.msg_class 	= M2UA_MCLASS_ASPSM;
					msg_ptr->comhdr.msg_type	= HEARTBEAT_ACK;
					len							= m2ua_sg_info[sg_id].msg_len;
					break;
				default:
					break;
			}
			break;
		}
		case M2UA_MCLASS_ASPTM:
		{	
			sid = 1;
			switch (msg_type)
			{
				case ASP_ACTIVE:
					//dw = htonl(M2UA_TRAFFIC_MODE_LOADSHARE);
					dw = htonl(M2UA_TRAFFIC_MODE_OVERRIDE);
					par_len = m2ua_make_par((m2ua_var_par_t *) &msg_ptr->msg[par_start],
										M2UA_PAR_TRAFFIC_MODE, (BYTE *)&dw, 4); 
					len							+= par_len;
					par_start 					+= par_len;
					if ((m2ua_para.sg_para[sg_id].xUA_ack>>1) == M3UA_APP)
					{
						dw = htonl(m2ua_sg_info[sg_id].rc);
						par_len = m2ua_make_par((m2ua_var_par_t *) &msg_ptr->msg[par_start],
									xUA_Routing_Context, (BYTE *)&dw, 4); 
						len					+= par_len;
						par_start 	+= par_len;
					}
					else
					{
						for (i = 0; i < M2UA_MAX_LK_NUM; i++)
						{
							if (m2ua_lk_info[i].enable && (m2ua_para.lk_para[i].lk_sg == sg_id))
							{
								dw = htonl(m2ua_para.lk_para[i].iid);
								par_len = m2ua_make_par((m2ua_var_par_t *) &msg_ptr->msg[par_start],
											M2UA_PAR_INTERFACE_ID_INT, (BYTE *)&dw, 4); 
								len					+= par_len;
								par_start 			+= par_len;
							}
						}
					}
					msg_ptr->comhdr.msg_class 	= M2UA_MCLASS_ASPTM;
					msg_ptr->comhdr.msg_type	= ASP_ACTIVE;
					len							+= sizeof(m2ua_comhdr_t);
					break;
				case ASP_INACTIVE:
					break;
				case ASP_ACTIVE_ACK:
					dw = htonl(M2UA_TRAFFIC_MODE_OVERRIDE);
					par_len = m2ua_make_par((m2ua_var_par_t *) &msg_ptr->msg[par_start],
										M2UA_PAR_TRAFFIC_MODE, (BYTE *)&dw, 4); 
					len								+= par_len;
					if ((m2ua_para.sg_para[sg_id].xUA_ack>>1) == M3UA_APP)
					{	
						par_start 					+= par_len;
						dw = htonl(m2ua_sg_info[sg_id].rc);
						par_len = m2ua_make_par((m2ua_var_par_t *) &msg_ptr->msg[par_start],
									xUA_Routing_Context, (BYTE *)&dw, 4); 
						len		+= par_len;						
					}
					msg_ptr->comhdr.msg_class 	= M2UA_MCLASS_ASPTM;
					msg_ptr->comhdr.msg_type	= ASP_ACTIVE_ACK;
					len							+= sizeof(m2ua_comhdr_t);
					break;
				case ASP_INACTIVE_ACK:
					if ((m2ua_para.sg_para[sg_id].xUA_ack>>1) == M3UA_APP)
					{	
						lk 		= m2ua_sg_info[sg_id].iid & 0xFF;
						dw = htonl(m2ua_sg_info[sg_id].rc);
						par_len = m2ua_make_par((m2ua_var_par_t *) &msg_ptr->msg[par_start],
									xUA_Routing_Context, (BYTE *)&dw, 4); 
						len		+= par_len;						
					}					
					msg_ptr->comhdr.msg_class 	= M2UA_MCLASS_ASPTM;
					msg_ptr->comhdr.msg_type	= ASP_INACTIVE_ACK;
					len							+= sizeof(m2ua_comhdr_t);
					break;
				default:
					break;
			}
			break;
		}
		case M2UA_MCLASS_MAUP:
		{	
			lk 		= m2ua_sg_info[sg_id].iid & 0xFF;
			iid		= m2ua_para.lk_para[lk].iid;
			msg_len	= m2ua_sg_info[sg_id].msg_len;
			sid		= m2ua_lk_info[lk].sid;
			dw		= htonl(iid);
			par_len = m2ua_make_par((m2ua_var_par_t *) &msg_ptr->msg[par_start],
									M2UA_PAR_INTERFACE_ID_INT, (BYTE *) &dw, 4);
			len		+= par_len;
			switch (msg_type)
			{
				case DATA:
					par_start 	+= par_len;
					par_len = m2ua_make_par((m2ua_var_par_t *) &msg_ptr->msg[par_start],
									M2UA_PAR_PROTO_DATA_1, m2ua_sg_info[sg_id].msg + 20, msg_len);
					len			+= par_len;
					msg_ptr->comhdr.msg_class 	= M2UA_MCLASS_MAUP;
					msg_ptr->comhdr.msg_type	= DATA;
					len							+= sizeof(m2ua_comhdr_t);
					
					m2ua_csta.sg_csta[sg_id].sg_out_msg++;
					m2ua_csta.lk_csta[lk].lk_out_msg++;
					m2ua_csta.sg_csta[sg_id].sg_out_bytes += msg_len;
					m2ua_csta.lk_csta[lk].lk_out_bytes += msg_len;
					err[3]++;
					break;
				case ESTABLISH_REQ:
					msg_ptr->comhdr.msg_class 	= M2UA_MCLASS_MAUP;
					msg_ptr->comhdr.msg_type	= ESTABLISH_REQ;
					len							+= sizeof(m2ua_comhdr_t);
					break;
				case ESTABLISH_CFM:
					msg_ptr->comhdr.msg_class 	= M2UA_MCLASS_MAUP;
					msg_ptr->comhdr.msg_type	= ESTABLISH_CFM;
					len							+= sizeof(m2ua_comhdr_t);
					break;
				case RELEASE_REQ:
					msg_ptr->comhdr.msg_class 	= M2UA_MCLASS_MAUP;
					msg_ptr->comhdr.msg_type	= RELEASE_REQ;
					len							+= sizeof(m2ua_comhdr_t);
					break;
				case RELEASE_CFM:
					msg_ptr->comhdr.msg_class 	= M2UA_MCLASS_MAUP;
					msg_ptr->comhdr.msg_type	= RELEASE_CFM;
					len							+= sizeof(m2ua_comhdr_t);
					break;
				case RELEASE_IND:
					msg_ptr->comhdr.msg_class 	= M2UA_MCLASS_MAUP;
					msg_ptr->comhdr.msg_type	= RELEASE_IND;
					len							+= sizeof(m2ua_comhdr_t);
					break;
				case STATE_REQ:
					dw			= htonl(m2ua_sg_info[sg_id].state);
					par_start 	+= par_len;
					par_len = m2ua_make_par((m2ua_var_par_t *) &msg_ptr->msg[par_start],
									M2UA_PAR_STATE, (BYTE *) &dw, 4);
					len			+= par_len;
					msg_ptr->comhdr.msg_class 	= M2UA_MCLASS_MAUP;
					msg_ptr->comhdr.msg_type	= STATE_REQ;
					len							+= sizeof(m2ua_comhdr_t);
					break;
				case STATE_CFM:
					dw			= htonl(m2ua_sg_info[sg_id].state);
					par_start 	+= par_len;
					par_len = m2ua_make_par((m2ua_var_par_t *) &msg_ptr->msg[par_start],
									M2UA_PAR_STATE, (BYTE *) &dw, 4);
					len			+= par_len;
					msg_ptr->comhdr.msg_class 	= M2UA_MCLASS_MAUP;
					msg_ptr->comhdr.msg_type	= STATE_CFM;
					len							+= sizeof(m2ua_comhdr_t);
					break;
				case STATE_IND:
					break;
				case DATA_RETIEVE_REQ:
				case DATA_RETIEVE_CFM:
				case DATA_RETIEVE_IND:
				case DATA_RETIEVE_CMP:
				case CONGESTION_IND:
					break;
				case DATA_ACK:
					dw			= htonl(m2ua_sg_info[sg_id].cor_id);
					par_start 	+= par_len;
					par_len = m2ua_make_par((m2ua_var_par_t *) &msg_ptr->msg[par_start],
									M2UA_PAR_CORRELATION_ID, (BYTE *) &dw, 4);
					len			+= par_len;
					msg_ptr->comhdr.msg_class 	= M2UA_MCLASS_MAUP;
					msg_ptr->comhdr.msg_type	= DATA_ACK;
					len							+= sizeof(m2ua_comhdr_t);
					break;
				default:
					break;
			}
			break;
		}
		case xUA_MCLASS_QPTM:
		{	
			lk 		= m2ua_sg_info[sg_id].iid & 0xFF;
			iid		= m2ua_para.lk_para[lk].iid;
			msg_len	= m2ua_sg_info[sg_id].msg_len;
			sid		= m2ua_lk_info[lk].sid;
			dw		= htonl(iid);
			par_len = m2ua_make_par((m2ua_var_par_t *) &msg_ptr->msg[par_start],
									M2UA_PAR_INTERFACE_ID_INT, (BYTE *) &dw, 4);
			len		+= par_len;			
			//DLCI
			par_start 	+= par_len;
			dlci		= m2ua_para.lk_para[lk].dlci;			
			dw			= htons(dlci) << 16;
			par_len = m2ua_make_par((m2ua_var_par_t *) &msg_ptr->msg[par_start],
							xUA_PAR_DLCI, (BYTE *) &dw, 4);
			len			+= par_len;						
			switch (msg_type)
			{
				case IUA_UDATA_REQ:
				case IUA_UDATA_IND:
					break;				
				case IUA_DATA_REQ:
				case IUA_DATA_IND:
					par_start 	+= par_len;
					par_len = m2ua_make_par((m2ua_var_par_t *) &msg_ptr->msg[par_start],
									xUA_PAR_PROTOCOL_DATA, m2ua_sg_info[sg_id].msg + 28, msg_len);
					len			+= par_len;
					msg_ptr->comhdr.msg_class 	= xUA_MCLASS_QPTM;
					msg_ptr->comhdr.msg_type		= msg_type;
					len							+= sizeof(m2ua_comhdr_t);
					
					m2ua_csta.sg_csta[sg_id].sg_out_msg++;
					m2ua_csta.lk_csta[lk].lk_out_msg++;
					m2ua_csta.sg_csta[sg_id].sg_out_bytes += msg_len;
					m2ua_csta.lk_csta[lk].lk_out_bytes += msg_len;
					err[3]++;
					break;
				case IUA_ESTABLISH_REQ:	
				case IUA_ESTABLISH_CFM:
				case IUA_ESTABLISH_IND:
					msg_ptr->comhdr.msg_class = xUA_MCLASS_QPTM;
					msg_ptr->comhdr.msg_type	= msg_type;
					len							+= sizeof(m2ua_comhdr_t);
					break;
				case IUA_RELEASE_REQ:
				case IUA_RELEASE_IND:
					dw			= htonl(m2ua_sg_info[sg_id].rel_reason);
					par_start 	+= par_len;
					par_len = m2ua_make_par((m2ua_var_par_t *) &msg_ptr->msg[par_start],
									xUA_PAR_REL_REASON, (BYTE *) &dw, 4);
					len			+= par_len;					
					msg_ptr->comhdr.msg_class 	= xUA_MCLASS_QPTM;
					msg_ptr->comhdr.msg_type	= msg_type;
					len							+= sizeof(m2ua_comhdr_t);							
					break;		
				case IUA_RELEASE_CFM:
					msg_ptr->comhdr.msg_class 	= xUA_MCLASS_QPTM;
					msg_ptr->comhdr.msg_type	= msg_type;
					len							+= sizeof(m2ua_comhdr_t);
					break;
				default:
					break;
			}
			break;
		}
		case xUA_MCLASS_TRMSG:
		{				
			switch (msg_type)
			{
				case M3UA_DATA:
					lk 		= m2ua_sg_info[sg_id].iid & 0xFF;
					dw		= htonl(m2ua_sg_info[sg_id].rc);
					msg_len	= m2ua_sg_info[sg_id].msg_len;
					sid		= m2ua_lk_info[lk].sid;
					
					par_len = m2ua_make_par((m2ua_var_par_t *) &msg_ptr->msg[par_start],
											xUA_Routing_Context, (BYTE *) &dw, 4);
					len		+= par_len;
			
					par_start 	+= par_len;										
					par_len = m2ua_make_par((m2ua_var_par_t *) &msg_ptr->msg[par_start],
									M3UA_Protocol_Data, m2ua_sg_info[sg_id].msg + 20, msg_len+12);
					len			+= par_len;
					msg_ptr->comhdr.msg_class = xUA_MCLASS_TRMSG;
					msg_ptr->comhdr.msg_type	= msg_type;
					len							+= sizeof(m2ua_comhdr_t);
					break;
				default:
					break;
			}			
			break;
		}
		default:
			break;
	}
		
	if (len == 0)
		return 0;
	
	msg_ptr->comhdr.version	= 1;
	msg_ptr->comhdr.spare	= 0;
	msg_ptr->comhdr.len		= htonl(len);
	
	if ((moniter_fg & MONITOR_M2UA) == MONITOR_M2UA)
	{
		if (m2ua_sg_mon_fg[sg_id] == 1)
		{
			if (msg_class == M2UA_MCLASS_MAUP)
				sprintf(m2ua_ascitemp_buf, "Send %s to The Peer, sg=%d, lk=%d, sid=%d, len=%d\n\r", dec_m2ua_msg(msg), sg_id, lk, sid, len);
			else
				sprintf(m2ua_ascitemp_buf, "Send %s to The Peer, sg=%d, sid=%d, len=%d\n\r", dec_m2ua_msg(msg), sg_id, sid, len);
			m2ua_asciout_proc(m2ua_ascitemp_buf);
			m2ua_hex_to_ascii((BYTE *)msg_ptr, len, m2ua_ascitemp_buf);
			m2ua_asciout_proc(m2ua_ascitemp_buf);
			m2ua_asciout_proc("\n\r");
			flag = 1;
		}
	}
	if ((msg_class == M2UA_MCLASS_MAUP ||msg_class == xUA_MCLASS_QPTM) && !flag)
	{
		if ((moniter_fg & MONITOR_MAUP) == MONITOR_MAUP)
		{
			if ((m2ua_sg_mon_fg[sg_id] == 1) || (m2ua_lk_mon_fg[lk] == 1))
			{
				sprintf(m2ua_ascitemp_buf, "Send %s to The Peer, sg=%d, lk=%d, sid=%d, len=%d\n\r", dec_m2ua_msg(msg), sg_id, lk, sid, len);
				m2ua_asciout_proc(m2ua_ascitemp_buf);
				m2ua_hex_to_ascii((BYTE *)msg_ptr, len, m2ua_ascitemp_buf);
				m2ua_asciout_proc(m2ua_ascitemp_buf);
				m2ua_asciout_proc("\n\r");
			}
		}
	}
	
#ifndef _LKSCTP
	m2ua_sctp_opt_data.sid_val	= sid;
	m2ua_sctp_data.buf			= (BYTE *)msg_ptr;
	m2ua_sctp_optdata_req(m2ua_sg_info[sg_id].fd, sg_id, len);
#else
	m2ua_sctp_data.sid	= sid;
	m2ua_sctp_data.buf	= (BYTE *)msg_ptr;
	m2ua_sctp_optdata_req_lksctp(m2ua_sg_info[sg_id].fd, sg_id, len);
#endif

	return len;
}

int m2ua_find_link_by_sg_iid(WORD sg_id, WORD iid)
{
	int 		i;
	lk_para_t 	*lk_para;
	
	lk_para = &m2ua_para.lk_para[0];
	
	for (i = 0; i < M2UA_MAX_LK_NUM; i++)
	{
		if (m2ua_lk_info[i].enable && (lk_para->lk_sg%256 == sg_id%256) && (lk_para->iid == iid))
			return i;
		lk_para++;
	}
	
	return -1;
}

int m2ua_dec_par(WORD sg_id, m2ua_var_par_t	*par_ptr, WORD par_type)
{
	WORD 	len = 0, hdr_len;
	DWORD	*dw_ptr;
	WORD	*w_ptr;
	int		iid;

	hdr_len = ntohs(par_ptr->hdr.len);
	
	switch (par_type)
	{
		case M2UA_PAR_INTERFACE_ID_INT:
		{	
			if ((par_ptr->hdr.tag != htons(M2UA_PAR_INTERFACE_ID_INT)) &&
				(par_ptr->hdr.tag != htons(M2UA_PAR_INTERFACE_ID_TXT)))
				return 0;
			else if (par_ptr->hdr.tag != htons(M2UA_PAR_INTERFACE_ID_INT))
			{
				m2ua_sg_info[sg_id].err_code = M2UA_ERR_UNSUPPORTED_IIT;
				m2ua_send_msg(sg_id, M2UA_MGMT_ERROR);
				return -1;
			}
//			else if (hdr_len % 4)
//			{
//				m2ua_sg_info[sg_id].err_code = M2UA_ERR_PARA_FIELD_ERROR;
//				m2ua_send_msg(sg_id, M2UA_MGMT_ERROR);
//				return -1;
//			}
			else
			{
				dw_ptr 	= (DWORD *) &par_ptr->val[0];
				iid		= ntohl(*dw_ptr);
				if ((iid = m2ua_find_link_by_sg_iid(sg_id, iid)) < 0)
				{
					m2ua_sg_info[sg_id].err_code = M2UA_ERR_INVALID_IID;
					m2ua_send_msg(sg_id, M2UA_MGMT_ERROR);
					return -1;
				}
				else
					m2ua_sg_info[sg_id].iid = iid;
				len 	= ((hdr_len + 3) & 0xFFFC);
			}
			break;
		}
		case M2UA_PAR_PROTO_DATA_1:
		{	
			if (hdr_len <= (M2UA_MAX_MSG_LEN - 2))
			{
				m2ua_sg_info[sg_id].msg 	= &par_ptr->val[0];
				m2ua_sg_info[sg_id].msg_len = hdr_len - sizeof(m2ua_par_hdr_t);
				len							= (hdr_len + 3) & 0xFFFC;
			}
			break;
		}
		case M2UA_PAR_CORRELATION_ID:
		{	
			if (par_ptr->hdr.tag != htons(M2UA_PAR_CORRELATION_ID))
				m2ua_sg_info[sg_id].cor_id 	= 0;
			else
			{
				dw_ptr 						= (DWORD *) &par_ptr->val[0];
				m2ua_sg_info[sg_id].cor_id 	= ntohl(*dw_ptr);
				len 						= ((hdr_len + 3) & 0xFFFC);
			}
			break;
		}
		case M2UA_PAR_STATE:
		{	
			dw_ptr 						= (DWORD *) &par_ptr->val[0];
			m2ua_sg_info[sg_id].state 	= ntohl(*dw_ptr);
			if (m2ua_sg_info[sg_id].state > M2UA_STATUS_CONG_DISCARD)
			{
				m2ua_sg_info[sg_id].err_code = M2UA_ERR_INVALID_PARA_VAL;
				m2ua_send_msg(sg_id, M2UA_MGMT_ERROR);
			}
			else
				len = ((hdr_len + 3) & 0xFFFC);
			break;
		}
		case M2UA_PAR_TRAFFIC_MODE:
		{	
			dw_ptr 								= (DWORD *) &par_ptr->val[0];
			m2ua_sg_info[sg_id].tra_hdl_mode 	= ntohl(*dw_ptr);
			if (m2ua_sg_info[sg_id].tra_hdl_mode != M2UA_TRAFFIC_MODE_OVERRIDE)
			{
				m2ua_sg_info[sg_id].err_code = M2UA_ERR_UNSUPPORTED_TRA_HDL_MODE;
				m2ua_send_msg(sg_id, M2UA_MGMT_ERROR);
			}
			else
				len = ((hdr_len + 3) & 0xFFFC);
			break;
		}
		case xUA_PAR_DLCI:
		{
			if (par_ptr->hdr.tag != htons(xUA_PAR_DLCI))
				m2ua_sg_info[sg_id].dlci 	= 0;
			else
			{
				w_ptr 						= (WORD *) &par_ptr->val[0];
				m2ua_sg_info[sg_id].dlci 	= ntohl(*w_ptr);
				len 						= ((hdr_len + 3) & 0xFFFC);
			}
			break;		
		}
		case xUA_PAR_REL_REASON:
		{	
			if (par_ptr->hdr.tag != htons(xUA_PAR_REL_REASON))
				m2ua_sg_info[sg_id].rel_reason 	= 0;
			else
			{
				dw_ptr 						= (DWORD *) &par_ptr->val[0];
				m2ua_sg_info[sg_id].rel_reason 	= ntohl(*dw_ptr);
				len 						= ((hdr_len + 3) & 0xFFFC);
			}
			break;
		}					
		case xUA_PAR_PROTOCOL_DATA:
		{	
			if (hdr_len <= (M2UA_MAX_MSG_LEN - XUAHEADOFFSET))
			{
				m2ua_sg_info[sg_id].msg 	= &par_ptr->val[0];
				m2ua_sg_info[sg_id].msg_len = hdr_len - sizeof(m2ua_par_hdr_t);
				len							= (hdr_len + 3) & 0xFFFC;
			}
			break;	
		}

		case M3UA_Network_Appearance:
		{	
			if (par_ptr->hdr.tag != htons(par_type))
				return 0;
			else
			{
				dw_ptr 						= (DWORD *) &par_ptr->val[0];
				m2ua_sg_info[sg_id].net_app 	= ntohl(*dw_ptr);
				len 						= ((hdr_len + 3) & 0xFFFC);
			}
			break;		
		}
		case xUA_Routing_Context:
		{	
			if (par_ptr->hdr.tag != htons(par_type))
				return 0;
			else
			{
				int RCn,ii;
				RCn = ((hdr_len- 4 + 3) & 0xFFFC) >> 2;
				for(ii=0;ii<RCn;ii++)
				{
					dw_ptr = (DWORD *) &par_ptr->val[ii*4];
					m2ua_sg_info[sg_id].rc 	= ntohl(*dw_ptr);
					if (check_m3ua_rc_verify(ntohl(*dw_ptr)) < 0)
					{
						m2ua_sg_info[sg_id].err_code = M3UA_ERR_INVALID_RC;
						m2ua_send_msg(sg_id, M2UA_MGMT_ERROR);
					}
					else
					{
						if (m2ua_sg_info[sg_id].m2ua_state == 3)
						{	
							switch(m2ua_sg_info[sg_id].m2ua_cmd)
							{
								case M2UA_ASPTM_ASP_ACTIVE:
									m3ua_sd_mtp3_user_rc_cmd(sg_id, M3UA_RC_UP);
									m2ua_send_msg(sg_id, M2UA_ASPTM_ASP_ACTIVE_ACK);
									if(m2ua_sg_info[sg_id].status != ((M2UA_STATUS_TYPE_AS_STATE_CHG << 16)|M2UA_STATUS_INFO_AS_ACTIVE))
									{	
										m2ua_sg_info[sg_id].status = (M2UA_STATUS_TYPE_AS_STATE_CHG << 16)|M2UA_STATUS_INFO_AS_ACTIVE;
										m2ua_send_msg(sg_id, M2UA_MGMT_NOTIFY);
									}									
									break;
								case M2UA_ASPTM_ASP_INACTIVE:
									m3ua_sd_mtp3_user_rc_cmd(sg_id, M3UA_RC_DOWN);
									m2ua_send_msg(sg_id, M2UA_ASPTM_ASP_INACTIVE_ACK);
									if(m2ua_sg_info[sg_id].status != ((M2UA_STATUS_TYPE_AS_STATE_CHG << 16)|M2UA_STATUS_INFO_AS_PENDING))
									{
										m2ua_sg_info[sg_id].status = (M2UA_STATUS_TYPE_AS_STATE_CHG << 16) | M2UA_STATUS_INFO_AS_PENDING;
										m2ua_send_msg(sg_id, M2UA_MGMT_NOTIFY);									
									}
									break;
								case M3UA_MAUP_DATA:
									break;
								case M3UA_SSNM_DUNA:
									m3ua_sd_mtp3_user_rc_cmd(sg_id, M3UA_RC_DOWN);
									break;
								case M3UA_SSNM_DAVA:
									m3ua_sd_mtp3_user_rc_cmd(sg_id, M3UA_RC_UP);
									break;
							}
						}
					}
				}
				len 						= ((hdr_len + 3) & 0xFFFC);
			}
			break;		
		}
		case M3UA_Protocol_Data:
		{	
			if (hdr_len <= (M2UA_MAX_MSG_LEN - 2))
			{
				dw_ptr 						= (DWORD *) &par_ptr->val[0];
				m2ua_sg_info[sg_id].opc 	= ntohl(*dw_ptr);
				
				dw_ptr 						= (DWORD *) &par_ptr->val[4];
				m2ua_sg_info[sg_id].dpc 	= ntohl(*dw_ptr);
				
				m2ua_sg_info[sg_id].si 	= par_ptr->val[8];
				m2ua_sg_info[sg_id].ni 	= par_ptr->val[9];
				m2ua_sg_info[sg_id].mp 	= par_ptr->val[10];
				m2ua_sg_info[sg_id].sls 	= par_ptr->val[11];
				
				m2ua_sg_info[sg_id].msg 	= &par_ptr->val[12];
				m2ua_sg_info[sg_id].msg_len = hdr_len - 12  - sizeof(m2ua_par_hdr_t);
				len							= (hdr_len + 3) & 0xFFFC;
			}
			break;
		}
		case xUA_Affected_PC:
		{	
			if (par_ptr->hdr.tag != htons(par_type))
				return 0;
			else
			{
				dw_ptr 						= (DWORD *) &par_ptr->val[0];
				m2ua_sg_info[sg_id].aff_pc 	= ntohl(*dw_ptr);
				len 						= ((hdr_len + 3) & 0xFFFC);
			}
			break;		
		}
		case M3UA_User_Cause:
		{	
			if (par_ptr->hdr.tag != htons(par_type))
				return 0;
			else
			{
				dw_ptr 						= (DWORD *) &par_ptr->val[0];
				m2ua_sg_info[sg_id].user_cause 	= ntohl(*dw_ptr);
				len 						= ((hdr_len + 3) & 0xFFFC);
			}
			break;		
		}
		case M3UA_Congestion_Indications:
		{	
			if (par_ptr->hdr.tag != htons(par_type))
				return 0;
			else
			{
				dw_ptr 						= (DWORD *) &par_ptr->val[0];
				m2ua_sg_info[sg_id].cong_ind 	= ntohl(*dw_ptr);
				len 						= ((hdr_len + 3) & 0xFFFC);
			}
			break;		
		}
		case M3UA_Concerned_Destination:
		{	
			if (par_ptr->hdr.tag != htons(par_type))
				return 0;
			else
			{
				dw_ptr 						= (DWORD *) &par_ptr->val[0];
				m2ua_sg_info[sg_id].con_dpc 	= ntohl(*dw_ptr);
				len 						= ((hdr_len + 3) & 0xFFFC);
			}
			break;		
		}
		default:
			break;
	}
	
	return len;
}

int m2ua_dec_msg(WORD sg_id)
{
	BYTE		server, m2ua_state, flag = 0;
	m2ua_msg_t	*msg_ptr;
	
	WORD		msg_sg,msg_len, par_start = 0;
	int			par_len = 0;
	BYTE		msg_class, msg_type;
	WORD		msg = M2UA_CMD_IDLEW;

	WORD		iid;
	WORD		mtp3_msg_len;
	DWORD		comm_len;

#ifndef _LKSCTP	
	msg_len 	= m2ua_sctp_data.len;
#else
	msg_len 	= m2ua_sctp_dat_len;
#endif

	msg_ptr 	= (m2ua_msg_t *) m2ua_sctp_dat;
	
	msg_class 	= msg_ptr->comhdr.msg_class;
	msg_type 	= msg_ptr->comhdr.msg_type;
	comm_len	= ntohl(msg_ptr->comhdr.len);
	
	server		= m2ua_para.sg_para[sg_id].server;
	m2ua_state	= m2ua_sg_info[sg_id].m2ua_state;
	
	if ((moniter_fg & MONITOR_M2UA) == MONITOR_M2UA)
	{
		if (m2ua_sg_mon_fg[sg_id] == 1)
		{
			sprintf(m2ua_ascitemp_buf, "Recv %s from The Peer, sg=%d, len=%d\n\r", dec_m2ua_msg((msg_class << 8) | msg_type), sg_id, msg_len);
			m2ua_asciout_proc(m2ua_ascitemp_buf);
			m2ua_hex_to_ascii(m2ua_sctp_dat, msg_len, m2ua_ascitemp_buf);
			m2ua_asciout_proc(m2ua_ascitemp_buf);
			m2ua_asciout_proc("\n\r");
			flag = 1;
		}
	}
	
	if (msg_ptr->comhdr.version != 1)
	{
		m2ua_sg_info[sg_id].err_code = M2UA_ERR_INVALID_VERSION;
		m2ua_send_msg(sg_id, M2UA_MGMT_ERROR);
		return -1;
	}
//	else if (comm_len % 4)
//	{
//		m2ua_sg_info[sg_id].err_code = M2UA_ERR_PARA_FIELD_ERROR;
//		m2ua_send_msg(sg_id, M2UA_MGMT_ERROR);
//		return -1;
//	}
	
	err[6]++;
	
	switch (msg_class)
	{
		case M2UA_MCLASS_MGMT:
		{	
			err[7]++;
			if ((msg_type > TEI_S_IND))
			//if ((msg_type != ERROR) && (msg_type != NOTIFY))
			{
				m2ua_sg_info[sg_id].err_code = M2UA_ERR_UNSUPPORTED_MSG_TYPE;
				m2ua_send_msg(sg_id, M2UA_MGMT_ERROR);
			}
			else if ((msg_type == xUA_NOTIFY) && server)
			{
				m2ua_sg_info[sg_id].err_code = M2UA_ERR_PROTOCOL_ERROR;
				m2ua_send_msg(sg_id, M2UA_MGMT_ERROR);
			}
			else if (msg_type == xUA_ERROR)
				msg = M2UA_MGMT_ERROR;
			break;
		}
		case M2UA_MCLASS_ASPSM:
		{	
			err[8]++;
			switch (msg_type)
			{
				case ASP_UP:
					msg = M2UA_ASPSM_ASP_UP;
					break;
				case ASP_DOWN:
					msg = M2UA_ASPSM_ASP_DOWN;
					break;
				case HEARTBEAT:
					m2ua_sg_info[sg_id].msg_len = msg_len;
					m2ua_send_msg(sg_id, M2UA_ASPSM_HEARTBEAT_ACK);
					break;
				case ASP_UP_ACK:
					msg = M2UA_ASPSM_ASP_UP_ACK;
					break;
				case ASP_DOWN_ACK:
					msg = M2UA_ASPSM_ASP_DOWN_ACK;
					break;
				case HEARTBEAT_ACK:
					msg = M2UA_ASPSM_HEARTBEAT_ACK;
					break;
				default:
					m2ua_sg_info[sg_id].err_code = M2UA_ERR_UNSUPPORTED_MSG_TYPE;
					m2ua_send_msg(sg_id, M2UA_MGMT_ERROR);
					break;
			}
			break;
		}
		case M2UA_MCLASS_ASPTM:
		{	
			err[9]++;
			switch (msg_type)
			{
				case ASP_ACTIVE:
					if (comm_len > sizeof(m2ua_comhdr_t))
					{  
						par_len = m2ua_dec_par(sg_id, (m2ua_var_par_t *) &(msg_ptr->msg[par_start]), M2UA_PAR_TRAFFIC_MODE);
						par_start 	+= par_len;
						m2ua_sg_info[sg_id].m2ua_cmd = M2UA_ASPTM_ASP_ACTIVE;
						par_len 	= m2ua_dec_par(sg_id, (m2ua_var_par_t *) &(msg_ptr->msg[par_start]), xUA_Routing_Context);
						m2ua_sg_info[sg_id].m2ua_cmd = 0;
						if(par_len >= 0)
							msg = M2UA_ASPTM_ASP_ACTIVE;	
					}
					else
						msg = M2UA_ASPTM_ASP_ACTIVE;
					break;
				case ASP_INACTIVE:
					m2ua_sg_info[sg_id].m2ua_cmd = M2UA_ASPTM_ASP_INACTIVE;
					par_len 	= m2ua_dec_par(sg_id, (m2ua_var_par_t *) &(msg_ptr->msg[par_start]), xUA_Routing_Context);
					m2ua_sg_info[sg_id].m2ua_cmd = 0;
					msg = M2UA_ASPTM_ASP_INACTIVE;
					break;
				case ASP_ACTIVE_ACK:
					msg = M2UA_ASPTM_ASP_ACTIVE_ACK;
//					par_len 	= m2ua_dec_par(sg_id, (m2ua_var_par_t *) &(msg_ptr->msg[par_start]), xUA_Routing_Context);
//					{                               
//						int lk;						                       
//						for (lk = 0; lk < M2UA_MAX_LK_NUM; lk++)
//						{                             
//							if ((m2ua_para.lk_para[lk].lk_sg == sg_id) && m2ua_lk_info[lk].enable)
//								m2ua_lk_info[lk].lk_act = 1;
//						}                     
//					}					                        
					break;                     
				case ASP_INACTIVE_ACK:              
					msg = M2UA_ASPTM_ASP_INACTIVE_ACK;
					break;
				default:
					m2ua_sg_info[sg_id].err_code = M2UA_ERR_UNSUPPORTED_MSG_TYPE;
					m2ua_send_msg(sg_id, M2UA_MGMT_ERROR);
					break;
			}
			break;
		}
		case M2UA_MCLASS_MAUP:
		{	
			err[10]++;
			if (m2ua_state != 3||(m2ua_para.sg_para[sg_id].xUA_ack>>1)!=M2UA_APP)
			{
				m2ua_sg_info[sg_id].err_code = M2UA_ERR_UNEXPECTED_MSG;
				m2ua_send_msg(sg_id, M2UA_MGMT_ERROR);
				return -1;
			}
			
			par_len = m2ua_dec_par(sg_id, (m2ua_var_par_t *) &(msg_ptr->msg[par_start]), M2UA_PAR_INTERFACE_ID_INT);
			if (par_len <= 0)
			{
				if (par_len == 0)
				{
					m2ua_sg_info[sg_id].err_code = M2UA_ERR_MISSING_PARA;
					m2ua_send_msg(sg_id, M2UA_MGMT_ERROR);
				}
				return -1;
			}
			
			iid 	= m2ua_sg_info[sg_id].iid;
			msg_sg	= m2ua_para.lk_para[iid].lk_sg;
			
			if ((iid >= M2UA_MAX_LK_NUM) ||
				(msg_sg != sg_id))
			{
				m2ua_sg_info[sg_id].err_code = M2UA_ERR_INVALID_IID;
				m2ua_send_msg(sg_id, M2UA_MGMT_ERROR);
				return -1;
			}
			
			err[11]++;
			
			if (((moniter_fg & MONITOR_MAUP) == MONITOR_MAUP) && !flag)
			{
				if ((m2ua_sg_mon_fg[sg_id] == 1) || (m2ua_lk_mon_fg[iid] == 1))
				{
					sprintf(m2ua_ascitemp_buf, "Recv %s from The Peer, sg=%d, lk=%d, len=%d\n\r", dec_m2ua_msg((msg_class << 8) | msg_type), sg_id, iid, msg_len);
					m2ua_asciout_proc(m2ua_ascitemp_buf);
					m2ua_hex_to_ascii(m2ua_sctp_dat, msg_len, m2ua_ascitemp_buf);
					m2ua_asciout_proc(m2ua_ascitemp_buf);
					m2ua_asciout_proc("\n\r");
				}
			}
			
			switch (msg_type)
			{
				case DATA:
					par_start 	+= par_len;
					par_len 	= m2ua_dec_par(sg_id, (m2ua_var_par_t *) &(msg_ptr->msg[par_start]), M2UA_PAR_PROTO_DATA_1);
					if (par_len > 0)
					{
						par_start 	+= par_len;
						par_len 	= m2ua_dec_par(sg_id, (m2ua_var_par_t *) &(msg_ptr->msg[par_start]), M2UA_PAR_CORRELATION_ID);
						msg 		= M2UA_MAUP_DATA;
					
						mtp3_msg_len = m2ua_sg_info[sg_id].msg_len;
						m2ua_csta.sg_csta[sg_id].sg_in_msg++;
						m2ua_csta.lk_csta[iid].lk_in_msg++;
						m2ua_csta.sg_csta[sg_id].sg_in_bytes += mtp3_msg_len;
						m2ua_csta.lk_csta[iid].lk_in_bytes += mtp3_msg_len;
						err[12]++;
					}
					break;
				case ESTABLISH_REQ:
					msg = M2UA_MAUP_ESTABLISH_REQ;
					break;
				case ESTABLISH_CFM:
					msg = M2UA_MAUP_ESTABLISH_CFM;
					break;
				case RELEASE_REQ:
					msg = M2UA_MAUP_RELEASE_REQ;
					break;
				case RELEASE_CFM:
					msg = M2UA_MAUP_RELEASE_CFM;
					break;
				case RELEASE_IND:
					msg = M2UA_MAUP_RELEASE_IND;
					break;
				case STATE_REQ:
					par_start 	+= par_len;
					par_len 	= m2ua_dec_par(sg_id, (m2ua_var_par_t *) &(msg_ptr->msg[par_start]), M2UA_PAR_STATE);
					if (par_len)
						msg	= M2UA_MAUP_STATE_REQ;
					break;
				case STATE_CFM:
					par_start 	+= par_len;
					par_len 	= m2ua_dec_par(sg_id, (m2ua_var_par_t *) &(msg_ptr->msg[par_start]), M2UA_PAR_STATE);
					break;
				case STATE_IND:
				case DATA_ACK:
					break;
				default:
					m2ua_sg_info[sg_id].err_code = M2UA_ERR_UNSUPPORTED_MSG_TYPE;
					m2ua_send_msg(sg_id, M2UA_MGMT_ERROR);
					break;
			}
			break;
		}
		case xUA_MCLASS_QPTM:
		{	
			err[10]++;
			if (m2ua_state != 3||(m2ua_para.sg_para[sg_id].xUA_ack>>1)!=IUA_APP)
			{
				m2ua_sg_info[sg_id].err_code = M2UA_ERR_UNEXPECTED_MSG;
				m2ua_send_msg(sg_id, M2UA_MGMT_ERROR);
				return -1;
			}
			
			par_len = m2ua_dec_par(sg_id, (m2ua_var_par_t *) &(msg_ptr->msg[par_start]), M2UA_PAR_INTERFACE_ID_INT);
			if (par_len <= 0)
			{
				if (par_len == 0)
				{
					m2ua_sg_info[sg_id].err_code = M2UA_ERR_MISSING_PARA;
					m2ua_send_msg(sg_id, M2UA_MGMT_ERROR);
				}
				return -1;
			}
			
			iid 	= m2ua_sg_info[sg_id].iid;
			msg_sg	= m2ua_para.lk_para[iid].lk_sg;

			
			if ((iid >= M2UA_MAX_LK_NUM) ||
				(msg_sg != sg_id))
			{
				m2ua_sg_info[sg_id].err_code = M2UA_ERR_INVALID_IID;
				m2ua_send_msg(sg_id, M2UA_MGMT_ERROR);
				return -1;
			}
			par_start 	+= par_len;
			par_len = m2ua_dec_par(sg_id, (m2ua_var_par_t *) &(msg_ptr->msg[par_start]), xUA_PAR_DLCI);
			if (par_len <= 0)
			{
				if (par_len == 0)
				{
					m2ua_sg_info[sg_id].err_code = M2UA_ERR_MISSING_PARA;
					m2ua_send_msg(sg_id, M2UA_MGMT_ERROR);
				}
				return -1;
			}
			err[11]++;
			
			if (((moniter_fg & MONITOR_MAUP) == MONITOR_MAUP) && !flag)
			{
				if ((m2ua_sg_mon_fg[sg_id] == 1) || (m2ua_lk_mon_fg[iid] == 1))
				{
					sprintf(m2ua_ascitemp_buf, "Recv %s from The Peer, sg=%d, lk=%d, len=%d\n\r", dec_m2ua_msg((msg_class << 8) | msg_type), sg_id, iid, msg_len);
					m2ua_asciout_proc(m2ua_ascitemp_buf);
					m2ua_hex_to_ascii(m2ua_sctp_dat, msg_len, m2ua_ascitemp_buf);
					m2ua_asciout_proc(m2ua_ascitemp_buf);
					m2ua_asciout_proc("\n\r");
				}
			}
			
			switch (msg_type)
			{
				case IUA_DATA_REQ:
				case IUA_DATA_IND:					
				case IUA_UDATA_REQ:
				case IUA_UDATA_IND:					
					par_start 	+= par_len;
					par_len 	= m2ua_dec_par(sg_id, (m2ua_var_par_t *) &(msg_ptr->msg[par_start]), xUA_PAR_PROTOCOL_DATA);
					if (par_len > 0)
					{
						msg 		= (xUA_MCLASS_QPTM << 8) + msg_type;
					
						mtp3_msg_len = m2ua_sg_info[sg_id].msg_len;
						m2ua_csta.sg_csta[sg_id].sg_in_msg++;
						m2ua_csta.lk_csta[iid].lk_in_msg++;
						m2ua_csta.sg_csta[sg_id].sg_in_bytes += mtp3_msg_len;
						m2ua_csta.lk_csta[iid].lk_in_bytes += mtp3_msg_len;
						err[12]++;
					}
					break;
				case IUA_ESTABLISH_REQ:
					msg = IUA_QPTM_ESTABLISH_REQ;
					break;
				case IUA_ESTABLISH_CFM:
					msg = IUA_QPTM_ESTABLISH_CFM;
					break;
				case IUA_ESTABLISH_IND:
					msg = IUA_QPTM_ESTABLISH_IND;
					break;					
				case IUA_RELEASE_REQ:
					par_start 	+= par_len;
					par_len 	= m2ua_dec_par(sg_id, (m2ua_var_par_t *) &(msg_ptr->msg[par_start]), xUA_PAR_REL_REASON);
					if (par_len)
						msg	= IUA_QPTM_RELEASE_REQ;
					break;					
				case IUA_RELEASE_CFM:
					par_start 	+= par_len;
					par_len 	= m2ua_dec_par(sg_id, (m2ua_var_par_t *) &(msg_ptr->msg[par_start]), xUA_PAR_REL_REASON);
					if (par_len)
						msg	= IUA_QPTM_RELEASE_CFM;
					break;
				case IUA_RELEASE_IND:
					msg = IUA_QPTM_RELEASE_IND;
					break;
				default:
					m2ua_sg_info[sg_id].err_code = M2UA_ERR_UNSUPPORTED_MSG_TYPE;
					m2ua_send_msg(sg_id, M2UA_MGMT_ERROR);
					break;
			}
			break;			
		}
		case xUA_MCLASS_TRMSG:
		{	
			err[10]++;
			if (m2ua_state != 3||(m2ua_para.sg_para[sg_id].xUA_ack>>1)!=M3UA_APP)
			{
				m2ua_sg_info[sg_id].err_code = M2UA_ERR_UNEXPECTED_MSG;
				m2ua_send_msg(sg_id, M2UA_MGMT_ERROR);
				return -1;
			}

			iid 	= m2ua_sg_info[sg_id].iid;
			if (((moniter_fg & MONITOR_MAUP) == MONITOR_MAUP) && !flag)
			{
				if ((m2ua_sg_mon_fg[sg_id] == 1) || (m2ua_lk_mon_fg[iid] == 1))
				{
					sprintf(m2ua_ascitemp_buf, "Recv %s from The Peer, sg=%d, lk=%d, len=%d\n\r", dec_m2ua_msg((msg_class << 8) | msg_type), sg_id, iid, msg_len);
					m2ua_asciout_proc(m2ua_ascitemp_buf);
					m2ua_hex_to_ascii(m2ua_sctp_dat, msg_len, m2ua_ascitemp_buf);
					m2ua_asciout_proc(m2ua_ascitemp_buf);
					m2ua_asciout_proc("\n\r");
				}
			}
			
			switch (msg_type)
			{
				case M3UA_DATA:
					par_len 	= m2ua_dec_par(sg_id, (m2ua_var_par_t *) &(msg_ptr->msg[par_start]), M3UA_Network_Appearance);
					par_start 	+= par_len;
					m2ua_sg_info[sg_id].m2ua_cmd = M3UA_MAUP_DATA;
					par_len 	= m2ua_dec_par(sg_id, (m2ua_var_par_t *) &(msg_ptr->msg[par_start]), xUA_Routing_Context);
					m2ua_sg_info[sg_id].m2ua_cmd =0;
					if (par_len <= 0)
					{
						if (par_len == 0)
						{
							m2ua_sg_info[sg_id].err_code = M2UA_ERR_MISSING_PARA;
							m2ua_send_msg(sg_id, M2UA_MGMT_ERROR);
						}
						return -1;
					}					
					par_start 	+= par_len;
					par_len 	= m2ua_dec_par(sg_id, (m2ua_var_par_t *) &(msg_ptr->msg[par_start]), M3UA_Protocol_Data);
					if (par_len > 0)
					{
						par_start 	+= par_len;
						par_len 	= m2ua_dec_par(sg_id, (m2ua_var_par_t *) &(msg_ptr->msg[par_start]), xUA_PAR_CORRELATION_ID);
						msg 		= (msg_class << 8) + msg_type;
						
						mtp3_msg_len = m2ua_sg_info[sg_id].msg_len;
						m2ua_csta.sg_csta[sg_id].sg_in_msg++;
						m2ua_csta.sg_csta[sg_id].sg_in_bytes += mtp3_msg_len;
						err[12]++;
					}
					break;
				default:
					m2ua_sg_info[sg_id].err_code = M2UA_ERR_UNSUPPORTED_MSG_TYPE;
					m2ua_send_msg(sg_id, M2UA_MGMT_ERROR);
					break;
			}			
			break;
		}
		case xUA_MCLASS_SSNM:
		{	
			err[10]++;
			if (m2ua_state != 3||(m2ua_para.sg_para[sg_id].xUA_ack>>1)!=M3UA_APP)
			{
				m2ua_sg_info[sg_id].err_code = M2UA_ERR_UNEXPECTED_MSG;
				m2ua_send_msg(sg_id, M2UA_MGMT_ERROR);
				return -1;
			}

			if (((moniter_fg & MONITOR_MAUP) == MONITOR_MAUP) && !flag)
			{
				if ((m2ua_sg_mon_fg[sg_id] == 1) || (m2ua_lk_mon_fg[iid] == 1))
				{
					sprintf(m2ua_ascitemp_buf, "Recv %s from The Peer, sg=%d, lk=%d, len=%d\n\r", dec_m2ua_msg((msg_class << 8) | msg_type), sg_id, iid, msg_len);
					m2ua_asciout_proc(m2ua_ascitemp_buf);
					m2ua_hex_to_ascii(m2ua_sctp_dat, msg_len, m2ua_ascitemp_buf);
					m2ua_asciout_proc(m2ua_ascitemp_buf);
					m2ua_asciout_proc("\n\r");
				}
			}
			par_len 	= m2ua_dec_par(sg_id, (m2ua_var_par_t *) &(msg_ptr->msg[par_start]), M3UA_Network_Appearance);
			par_start 	+= par_len;
			m2ua_sg_info[sg_id].m2ua_cmd = (msg_class << 8) + msg_type;
			par_len 	= m2ua_dec_par(sg_id, (m2ua_var_par_t *) &(msg_ptr->msg[par_start]), xUA_Routing_Context);
			m2ua_sg_info[sg_id].m2ua_cmd = 0;
			if (par_len <= 0)
			{
				if (par_len == 0)
				{
					m2ua_sg_info[sg_id].err_code = M2UA_ERR_MISSING_PARA;
					m2ua_send_msg(sg_id, M2UA_MGMT_ERROR);
				}
				return -1;
			}
			par_start 	+= par_len;
			par_len 	= m2ua_dec_par(sg_id, (m2ua_var_par_t *) &(msg_ptr->msg[par_start]), xUA_Affected_PC);
			if (par_len <= 0)
			{
				if (par_len == 0)
				{
					m2ua_sg_info[sg_id].err_code = M2UA_ERR_MISSING_PARA;
					m2ua_send_msg(sg_id, M2UA_MGMT_ERROR);
				}
				return -1;
			}
			switch (msg_type)
			{
				case SSNM_DUNA:
					msg 		= (msg_class << 8) + msg_type;
//					m3ua_sd_mtp3_user_rc_cmd(sg_id, M3UA_RC_DOWN);
					break;
				case SSNM_DAVA:		
					msg 		= (msg_class << 8) + msg_type;
//					m3ua_sd_mtp3_user_rc_cmd(sg_id, M3UA_RC_UP);
					break;
				case SSNM_DAUD:
					msg 		= (msg_class << 8) + msg_type;
					break;
				case SSNM_SCON:		
					msg 		= (msg_class << 8) + msg_type;
					break;
				case SSNM_DUPU:					
					par_start 	+= par_len;
					par_len 	= m2ua_dec_par(sg_id, (m2ua_var_par_t *) &(msg_ptr->msg[par_start]), M3UA_User_Cause);
					if (par_len <= 0)
					{
						if (par_len == 0)
						{
							m2ua_sg_info[sg_id].err_code = M2UA_ERR_MISSING_PARA;
							m2ua_send_msg(sg_id, M2UA_MGMT_ERROR);
						}
						return -1;
					}
					msg 		= (msg_class << 8) + msg_type;
					break;
				case SSNM_DRST:
					msg 		= (msg_class << 8) + msg_type;
					par_start 	+= par_len;
					par_len 	= m2ua_dec_par(sg_id, (m2ua_var_par_t *) &(msg_ptr->msg[par_start]), M3UA_Congestion_Indications);
					par_start 	+= par_len;
					par_len 	= m2ua_dec_par(sg_id, (m2ua_var_par_t *) &(msg_ptr->msg[par_start]), M3UA_Concerned_Destination);
					break;
				default:
					m2ua_sg_info[sg_id].err_code = M2UA_ERR_UNSUPPORTED_MSG_TYPE;
					m2ua_send_msg(sg_id, M2UA_MGMT_ERROR);
					break;
			}			
			break;		
		}
		default:
		{	
			m2ua_sg_info[sg_id].err_code = M2UA_ERR_UNSUPPORTED_MSG_CLASS;
			m2ua_send_msg(sg_id, M2UA_MGMT_ERROR);
			break;
		}
	}
	
	if (msg != M2UA_CMD_IDLEW)
	{
		m2ua_sg_info[sg_id].m2ua_cmd = msg;
		return 0;
	}
	else
		return -1;
}

int m2ua_sd_mtp3_primi(BYTE lk, BYTE primi)
{
	m2ua_up_msg_t *up_ptr;
	
	if (((m2ua_mtp3_sd_h + 1) & M2UA_MAX_M3MSG_NUM_1) == m2ua_mtp3_sd_t)
		return -1;
	
	up_ptr = (m2ua_up_msg_t *) (m2ua_mtp3_sd + x256[m2ua_mtp3_sd_h]);
	up_ptr->link 				= lk;
	up_ptr->len 				= htons(4);
	up_ptr->sio 				= M2UA_SIO_CMD;
	up_ptr->msg.lm.mtp3_ip		= 0;
	up_ptr->msg.lm.opercode		= primi;
	
	if ((m2ua_lk_info[lk].lk_st == M2UA_LK_UP) &&
		(m2ua_lk_info[lk].alarm_code != M2UA_ALARM_CODE_NORMAL))
		m2ua_lk_info[lk].alarm_code = M2UA_ALARM_CODE_NORMAL;
	up_ptr->msg.lm.alarmcode = m2ua_lk_info[lk].alarm_code;
	
	m2ua_mtp3_sd_h = (m2ua_mtp3_sd_h + 1) & M2UA_MAX_M3MSG_NUM_1;
	
	err[15]++;
	
	return 0;
}

int m2ua_sd_mtp3_msg(WORD sg, BYTE lk)
{
	BYTE 			*msg;
	int 			len;
	m2ua_up_msg_t 	*up_ptr;
	
	if (((m2ua_mtp3_sd_h + 1) & M2UA_MAX_M3MSG_NUM_1) == m2ua_mtp3_sd_t)
		return -1;
	
	len 					= m2ua_sg_info[sg].msg_len;
	msg						= m2ua_sg_info[sg].msg;
	
	up_ptr 					= (m2ua_up_msg_t *) (m2ua_mtp3_sd + x256[m2ua_mtp3_sd_h]);
	up_ptr->link 			= lk;
	up_ptr->len 			= htons(len);
	up_ptr->sio 			= *msg;
	
	bcopy(msg + 1, up_ptr->msg.mtp3.content, len);
	
	m2ua_mtp3_sd_h = (m2ua_mtp3_sd_h + 1) & M2UA_MAX_M3MSG_NUM_1;
	
	err[14]++;
	
	return 1;
}

int iua_sd_q931_primi(BYTE lk, BYTE primi)
{
	xua_up_msg_t *up_ptr;
	
	if (((iua_q931_sd_h + 1) & M2UA_MAX_M3MSG_NUM_1) == iua_q931_sd_t)
		return -1;
	
	up_ptr = (xua_up_msg_t *) (iua_q931_sd + x256[iua_q931_sd_h]);
	up_ptr->msg_class		= IUA_MGMT_CMD;
	
	up_ptr->msg.lm_lk.link			=	lk;
	up_ptr->msg.lm_lk.len 			= htons(3);
	up_ptr->msg.lm_lk.mtp3_ip		= 0;
	up_ptr->msg.lm_lk.opercode	= primi;
	
	if ((m2ua_lk_info[lk].lk_st == M2UA_LK_UP) &&
		(m2ua_lk_info[lk].alarm_code != M2UA_ALARM_CODE_NORMAL))
		m2ua_lk_info[lk].alarm_code = M2UA_ALARM_CODE_NORMAL;
		
	
	iua_q931_sd_h = (iua_q931_sd_h + 1) & M2UA_MAX_M3MSG_NUM_1;
	
	err[15]++;
	
	return 0;
}

int iua_sd_q931_msg(WORD sg, BYTE lk)
{
	BYTE 						*msg;
	int 						len;
	xua_up_msg_t	 	*up_ptr;
	
	if (((iua_q931_sd_h + 1) & M2UA_MAX_M3MSG_NUM_1) == iua_q931_sd_t)
		return -1;
	
	len 					= m2ua_sg_info[sg].msg_len;
	msg						= m2ua_sg_info[sg].msg;
	
	up_ptr 					= (xua_up_msg_t *) (iua_q931_sd + x256[iua_q931_sd_h]);
	up_ptr->msg_class		= IUA_QPTM_MSG;
	
	up_ptr->msg.iua.link			=	lk;
	up_ptr->msg.iua.len 			= htons(len);	
	bcopy(msg, up_ptr->msg.iua.content, len);
	
	iua_q931_sd_h = (iua_q931_sd_h + 1) & M2UA_MAX_M3MSG_NUM_1;
	
	err[14]++;
	
	return 1;
}

int m3ua_sd_mtp3_user_primi(BYTE lk, BYTE primi)
{
	xua_up_msg_t *up_ptr;
	
	if (((m3ua_mtp3_sd_h + 1) & M2UA_MAX_M3MSG_NUM_1) == m3ua_mtp3_sd_t)
		return -1;
	
	up_ptr = (xua_up_msg_t *) (m3ua_mtp3_sd + x256[m3ua_mtp3_sd_h]);
	up_ptr->msg_class		= M3UA_MGMT_CMD;
	
	up_ptr->msg.lm_lk.link		=	lk;
	up_ptr->msg.lm_lk.len 			= htons(3);
	up_ptr->msg.lm_lk.mtp3_ip		= 0;
	up_ptr->msg.lm_lk.opercode	= primi;	
	up_ptr->msg.lm_lk.alarmcode = m2ua_lk_info[lk].alarm_code;
	
	m3ua_mtp3_sd_h = (m3ua_mtp3_sd_h + 1) & M2UA_MAX_M3MSG_NUM_1;
	
	return 0;
}

int m3ua_sd_mtp3_user_rc_cmd(WORD sg, BYTE primi)
{
	xua_up_msg_t *up_ptr;
	WORD lk;

	for (lk = 0; lk < M2UA_MAX_LK_NUM; lk++)
	{
		if (((m3ua_mtp3_sd_h + 1) & M2UA_MAX_M3MSG_NUM_1) == m3ua_mtp3_sd_t)
			return -1;
		if ((m2ua_para.lk_para[lk].lk_sg == sg) &&	m2ua_lk_info[lk].enable)
		{				
			up_ptr = (xua_up_msg_t *) (m3ua_mtp3_sd + x256[m3ua_mtp3_sd_h]);
			up_ptr->msg_class		= M3UA_RC_CMD;
			
			up_ptr->msg.rc_cmd.link		=	lk;
			up_ptr->msg.rc_cmd.len 			= htons(5);
			up_ptr->msg.rc_cmd.opercode	= primi;	
			up_ptr->msg.rc_cmd.rc = m2ua_sg_info[sg].rc;
			
			m3ua_mtp3_sd_h = (m3ua_mtp3_sd_h + 1) & M2UA_MAX_M3MSG_NUM_1;
		}
	}
	
	return 0;
}

int m3ua_sd_mtp3_user_msg(WORD sg)
{
	BYTE 						*msg;
	int 						len,lk;
	xua_up_msg_t	 	*up_ptr;
	
	for (lk = 0; lk < M2UA_MAX_LK_NUM; lk++)
	{
		if (((m3ua_mtp3_sd_h + 1) & M2UA_MAX_M3MSG_NUM_1) == m3ua_mtp3_sd_t)
			return -1;
		if ((m2ua_para.lk_para[lk].lk_sg == sg) &&	m2ua_lk_info[lk].enable)
		{				
			len 		= m2ua_sg_info[sg].msg_len;
			msg			= m2ua_sg_info[sg].msg;			
			
			up_ptr = (xua_up_msg_t *) (m3ua_mtp3_sd + x256[m3ua_mtp3_sd_h]);
			up_ptr->msg_class		= M3UA_MAUP_MSG;
			
			up_ptr->msg.m3ua.link	=	lk;
			up_ptr->msg.m3ua.dpc	=	m2ua_sg_info[sg].dpc;
			up_ptr->msg.m3ua.opc	=	m2ua_sg_info[sg].opc;
			up_ptr->msg.m3ua.sls	=	m2ua_sg_info[sg].sls;
			up_ptr->msg.m3ua.mp	=	m2ua_sg_info[sg].mp;
			up_ptr->msg.m3ua.ni	=	m2ua_sg_info[sg].ni;
			up_ptr->msg.m3ua.si	=	m2ua_sg_info[sg].si;
		
			up_ptr->msg.m3ua.len 			= htons(len);	
			bcopy(msg, up_ptr->msg.m3ua.content, len);
			
			m3ua_mtp3_sd_h = (m3ua_mtp3_sd_h + 1) & M2UA_MAX_M3MSG_NUM_1;
			break;
		}
	}	

	return 0;
}


int m2ua_sg_init(WORD id)
{
	bzero((BYTE *)&m2ua_sg_info[id], sizeof(m2ua_sg_info_t));
	
	m2ua_sg_info[id].m2ua_cmd	= M2UA_CMD_IDLEW;
	m2ua_sg_info[id].sctp_cmd	= M2UA_CMD_IDLEW;
	m2ua_sg_info[id].mtp3_cmd	= M2UA_CMD_IDLEW;
	m2ua_sg_info[id].mgmt_cmd	= M2UA_CMD_IDLEW;

	return 0;
}

int m2ua_lk_init(BYTE id)
{
	WORD lk_sg;
	
	bzero(&m2ua_lk_info[id], sizeof(m2ua_lk_info_t));
	
	lk_sg = m2ua_para.lk_para[id].lk_sg;
	if (m2ua_sg_info[lk_sg].m2ua_state == 3)
		m2ua_lk_info[id].lk_st = M2UA_LK_DOWN;
	else
		m2ua_lk_info[id].lk_st = M2UA_LK_IDLE;
	
	return 0;
}

int enable_sg(WORD sg)
{
	int fd;

	if (m2ua_para.sg_para[sg].enable &&
		(m2ua_sg_info[sg].fd == 0))
	{
#ifndef _LKSCTP	
		if ((fd = m2ua_sctp_t_open(sg)) <= 0)
		{	
			m2ua_log_err(sg, "enable sg, open sctp fail!");
			return -1;
		}
		else
		{
			m2ua_sg_init(sg);
			m2ua_sg_info[sg].fd 	= fd;
			m2ua_sg_info[sg].enable = 1;
		}
#else
		if (!m2ua_para.sg_para[sg].server)
		{
			if ((fd = m2ua_sctp_open_lksctp(sg)) <= 0)
			{	
				m2ua_log_err(sg, "enable sg, open sctp fail!");
				return -1;
			}
			m2ua_sg_init(sg);
			m2ua_sg_info[sg].fd = fd;
		}
		else if (!m2ua_sg_info[sg].enable)
			m2ua_sg_init(sg);
		m2ua_sg_info[sg].enable = 1;
#endif
	}
	
	return 0;
}

int rm_sg_lk(WORD sg, BYTE lk)
{
	int fd;
	
	rel_sid(sg, lk);
	
	if (--m2ua_sg_info[sg].act_lks == 0)
	{
		fd = m2ua_sg_info[sg].fd;
		if (fd > 0)
		{
#ifndef _LKSCTP
			if ((m2ua_sg_info[sg].sctp_state > 2) ||
				((m2ua_sg_info[sg].sctp_state == 2) &&
				(m2ua_sg_info[sg].sctp_state_1 > 0)))
				m2ua_sctp_discon_req(fd, sg, 0);
			m2ua_sctp_close(fd, sg);
#else
			if ((m2ua_sg_info[sg].sctp_state > 2) ||
				((m2ua_sg_info[sg].sctp_state == 2) &&
				(m2ua_sg_info[sg].sctp_state_1 > 0)))
				m2ua_sctp_discon_req_lksctp(fd, sg, 0);
#endif
		}
		m2ua_sg_init(sg);
	}
	
	return 0;
}

int get_m2ua_msg(m2ua_up_msg_t **data_ptr)
{
	m2ua_up_msg_t 	*up_ptr;
	BYTE			lk;
	int 			len;
	WORD 			sg;
	
	if (m2ua_mtp3_sd_t == m2ua_mtp3_sd_h)
		return -1;
	
	up_ptr 	= (m2ua_up_msg_t *)(m2ua_mtp3_sd + x256[m2ua_mtp3_sd_t]);
	lk 		= up_ptr->link;
	len		= ntohs(up_ptr->len) + 3;
	sg 		= m2ua_para.lk_para[lk].lk_sg;
	*data_ptr = up_ptr;
	
	m2ua_mtp3_sd_t = (m2ua_mtp3_sd_t + 1) & M2UA_MAX_M3MSG_NUM_1;
	
	if ((moniter_fg & MONITOR_MTP3) == MONITOR_MTP3)
	{
		if ((m2ua_sg_mon_fg[sg] == 1) || (m2ua_lk_mon_fg[lk] == 1))
		{
			sprintf(m2ua_ascitemp_buf, "Send MSG to MTP3, sg=%d, lk=%d, len=%d\n\r", sg, lk, len);
			m2ua_asciout_proc(m2ua_ascitemp_buf);
			m2ua_hex_to_ascii((BYTE *)up_ptr, len, m2ua_ascitemp_buf);
			m2ua_asciout_proc(m2ua_ascitemp_buf);
			m2ua_asciout_proc("\n\r");
		}
	}
	
	err[16]++;
	
	return 0;
}

int put_m2ua_msg(m2ua_up_msg_t *data_ptr)
{
	BYTE lk;
	int 	len;	
	WORD	sg;
	
	lk = data_ptr->link;
	sg 	= m2ua_para.lk_para[lk].lk_sg;
	len	= ntohs(data_ptr->len);
	err[0]++;
	
	if ((moniter_fg & MONITOR_MTP3) == MONITOR_MTP3)
	{
		if ((m2ua_sg_mon_fg[sg] == 1) || (m2ua_lk_mon_fg[lk] == 1))
		{
			sprintf(m2ua_ascitemp_buf, "Recv MSG from MTP3, sg=%d, lk=%d, len=%d\n\r", sg, lk, len+3);
			m2ua_asciout_proc(m2ua_ascitemp_buf);
			m2ua_hex_to_ascii((BYTE *)data_ptr, len+3, m2ua_ascitemp_buf);
			m2ua_asciout_proc(m2ua_ascitemp_buf);
			m2ua_asciout_proc("\n\r");
		}
	}
	if ((m2ua_para.sg_para[sg].xUA_ack>>1) != M2UA_APP)
	{	
		m2ua_log_err(sg, "ERROR: SG type is not m2ua!");
		return -1;
	}	
	if (m2ua_para.lk_para[lk].enable == 0)
		return -1;
	if (m2ua_para.sg_para[sg].enable == 0)
		return -1;
	
	if (data_ptr->sio == M2UA_MTP3_SIO_CMD)
	{
		err[1]++;
		if ((data_ptr->msg.lm.opercode == M2UA_ENABLE_M2UA_LINK) && 
			(!m2ua_lk_info[lk].enable))
		{
			if (enable_sg(sg) < 0)
				return -1;
			
			m2ua_lk_init(lk);
			m2ua_lk_info[lk].enable = 1;
			m2ua_sg_info[sg].act_lks++;
		}
		else if ((data_ptr->msg.lm.opercode == M2UA_STOP_M2UA_LINK) &&
			m2ua_lk_info[lk].enable)
		{
			if (m2ua_sg_info[sg].m2ua_state == 3)
			{
				m2ua_sg_info[sg].iid 		= lk;
				m2ua_sg_info[sg].mgmt_cmd 	= M2UA_MGMT_CMD_LK_LOCK;
				m2ua_fsm(sg);
			}
			
			rm_sg_lk(sg, lk);
			m2ua_lk_init(lk);
			
			m2ua_lk_info[lk].enable = 0;
		}
		else if ((m2ua_sg_info[sg].m2ua_state == 3) && m2ua_lk_info[lk].enable)
		{
			m2ua_sg_info[sg].mtp3_cmd 	= data_ptr->msg.lm.opercode;
			m2ua_sg_info[sg].iid 		= lk;
			m2ua_fsm(sg);
		}
		return 0;
	}
	else if (m2ua_lk_info[lk].lk_st == M2UA_LK_UP)
	{
		err[2]++;
		if (len <= (M2UA_MAX_MSG_LEN - 2))
		{
			m2ua_sg_info[sg].iid 		= lk;
			m2ua_sg_info[sg].msg		= (BYTE *)data_ptr - 18 + 1;
			m2ua_sg_info[sg].msg_len	= len;
			m2ua_send_msg(sg, M2UA_MAUP_DATA);
			err[4]++;
			return 0;
		}
	}
	
	return -1;
}

int get_xua_msg(BYTE xUA_type, xua_up_msg_t **data_ptr)
{
	xua_up_msg_t 	*up_ptr;
	BYTE					lk;
	int 					len,msg_len;
	BYTE					*xua_msg_sd;
	WORD					sg, *xua_sd_h, *xua_sd_t;
	
	if(data_ptr == NULL)
		return -1;	
	
	switch (xUA_type)
	{
		case M2UA_APP:
			return -1;//reserve
			xua_msg_sd = m2ua_mtp3_sd;
			xua_sd_t = &m2ua_mtp3_sd_t;
			xua_sd_h = &m2ua_mtp3_sd_h;			
			break;
		case IUA_APP:	
			xua_msg_sd = iua_q931_sd;
			xua_sd_t = &iua_q931_sd_t;
			xua_sd_h = &iua_q931_sd_h;
			break;
		case M3UA_APP:
			xua_msg_sd = m3ua_mtp3_sd;
			xua_sd_t = &m3ua_mtp3_sd_t;
			xua_sd_h = &m3ua_mtp3_sd_h;			
			break;			
		default:
			return -1;		
	}
	if (*xua_sd_t == *xua_sd_h)
		return -1;
	
	up_ptr 	= (xua_up_msg_t *)(xua_msg_sd + x256[*xua_sd_t]);
	lk 		= up_ptr->msg.lm_lk.link;
	len		= ntohs(up_ptr->msg.lm_lk.len);		
	sg 		= m2ua_para.lk_para[lk].lk_sg;
	*data_ptr = up_ptr;
	
	*xua_sd_t = (*xua_sd_t + 1) & M2UA_MAX_M3MSG_NUM_1;
	
	if ((moniter_fg & MONITOR_MTP3) == MONITOR_MTP3)
	{
		if ((m2ua_sg_mon_fg[sg] == 1) || (m2ua_lk_mon_fg[lk] == 1))
		{
			sprintf(m2ua_ascitemp_buf, "Send MSG to UP LAYER, sg=%d, lk=%d, len=%d\n\r", sg, lk, len+XUAHEADOFFSET);
			m2ua_asciout_proc(m2ua_ascitemp_buf);
			m2ua_hex_to_ascii((BYTE *)up_ptr, len+XUAHEADOFFSET, m2ua_ascitemp_buf);
			m2ua_asciout_proc(m2ua_ascitemp_buf);
			m2ua_asciout_proc("\n\r");
		}
	}	
	err[16]++;
	msg_len = len+XUAHEADOFFSET;
	return msg_len;
}

int put_xua_msg(xua_up_msg_t *data_ptr)
{
	BYTE lk,	server;
	int 	len;
	WORD	sg;
	if(data_ptr == NULL)
		return -1;
		
	switch (data_ptr->msg_class)
	{
		case M2UA_MGMT_CMD:
		case IUA_MGMT_CMD:
		{
			lk  = data_ptr->msg.lm_lk.link;
			sg 	= m2ua_para.lk_para[lk].lk_sg;
			len	= ntohs(data_ptr->msg.lm_lk.len);
			err[0]++;
			if ((moniter_fg & MONITOR_MTP3) == MONITOR_MTP3)
			{
				if ((m2ua_sg_mon_fg[sg] == 1) || (m2ua_lk_mon_fg[lk] == 1))
				{
					sprintf(m2ua_ascitemp_buf, "Recv MSG from upper layer, sg=%d, lk=%d, len=%d\n\r", sg, lk, len + XUAHEADOFFSET);
					m2ua_asciout_proc(m2ua_ascitemp_buf);
					m2ua_hex_to_ascii((BYTE *)data_ptr, len + XUAHEADOFFSET, m2ua_ascitemp_buf);
					m2ua_asciout_proc(m2ua_ascitemp_buf);
					m2ua_asciout_proc("\n\r");
				}
			}
			
			if (m2ua_para.lk_para[lk].enable == 0)
				return -1;
			if (m2ua_para.sg_para[sg].enable == 0)
				return -1;			

			err[1]++;
			if ((data_ptr->msg.lm_lk.opercode == xUA_ENABLE_xUA_LINK) && 
				(!m2ua_lk_info[lk].enable))
			{
				if (enable_sg(sg) < 0)
					return -1;
				
				m2ua_lk_init(lk);
				m2ua_lk_info[lk].enable = 1;
				m2ua_sg_info[sg].act_lks++;
			}
			else if ((data_ptr->msg.lm_lk.opercode == xUA_STOP_xUA_LINK) &&
				m2ua_lk_info[lk].enable)
			{
				if (m2ua_sg_info[sg].m2ua_state == 3)
				{
					m2ua_sg_info[sg].iid 		= lk;
					m2ua_sg_info[sg].mgmt_cmd 	= COMBO_W(data_ptr->msg_class,M2UA_MGMT_CMD_LK_LOCK);
					m2ua_fsm(sg);
				}
				
				rm_sg_lk(sg, lk);
				m2ua_lk_init(lk);
				
				m2ua_lk_info[lk].enable = 0;
			}
			else if ((m2ua_sg_info[sg].m2ua_state == 3) && m2ua_lk_info[lk].enable)
			{
				m2ua_sg_info[sg].mtp3_cmd 	= COMBO_W(data_ptr->msg_class,data_ptr->msg.lm_lk.opercode);
				m2ua_sg_info[sg].iid 		= lk;
				m2ua_fsm(sg);
			}
			return 0;
		}
		case IUA_QPTM_MSG:
		{	
			lk 	= data_ptr->msg.iua.link;
			sg 	= m2ua_para.lk_para[lk].lk_sg;
			len	= ntohs(data_ptr->msg.iua.len);
			if ((m2ua_para.sg_para[sg].xUA_ack>>1) != IUA_APP)
			{	
				m2ua_log_err(sg, "ERROR: SG type is not iua!");
				return -1;
			}				
			err[0]++;			
			if ((moniter_fg & MONITOR_MTP3) == MONITOR_MTP3)
			{
				if ((m2ua_sg_mon_fg[sg] == 1) || (m2ua_lk_mon_fg[lk] == 1))
				{
					sprintf(m2ua_ascitemp_buf, "Recv MSG from Q931, sg=%d, lk=%d, len=%d\n\r", sg, lk, len+XUAHEADOFFSET);
					m2ua_asciout_proc(m2ua_ascitemp_buf);
					m2ua_hex_to_ascii((BYTE *)data_ptr, len+XUAHEADOFFSET, m2ua_ascitemp_buf);
					m2ua_asciout_proc(m2ua_ascitemp_buf);
					m2ua_asciout_proc("\n\r");
				}
			}			
			if (m2ua_para.lk_para[lk].enable == 0)
				return -1;
			if (m2ua_para.sg_para[sg].enable == 0)
				return -1;			
			if (m2ua_lk_info[lk].lk_st == M2UA_LK_UP)
			{
				err[2]++;
				if (len <= (M2UA_MAX_MSG_LEN - XUAHEADOFFSET))
				{
					m2ua_sg_info[sg].iid 		= lk;
					m2ua_sg_info[sg].msg		= (BYTE *)data_ptr - RESERVE_FOR_IUAHEAD;
					m2ua_sg_info[sg].msg_len	= len;
					server	= m2ua_para.sg_para[sg].server;
					if(server)
						m2ua_send_msg(sg, IUA_QPTM_DATA_IND);
					else
						m2ua_send_msg(sg, IUA_QPTM_DATA_REQ);	
					err[4]++;
					return 0;
				}
			}
			break;
		}				
		case M2UA_MAUP_MSG:
		{
			lk 	= data_ptr->msg.m2ua.link;
			sg 	= m2ua_para.lk_para[lk].lk_sg;
			len	= ntohs(data_ptr->msg.m2ua.len);
			if ((m2ua_para.sg_para[sg].xUA_ack>>1) != M2UA_APP)
			{	
				m2ua_log_err(sg, "ERROR: SG type is not m2ua!");
				return -1;
			}							
			err[0]++;			
			if ((moniter_fg & MONITOR_MTP3) == MONITOR_MTP3)
			{
				if ((m2ua_sg_mon_fg[sg] == 1) || (m2ua_lk_mon_fg[lk] == 1))
				{
					sprintf(m2ua_ascitemp_buf, "Recv MSG from Q931, sg=%d, lk=%d, len=%d\n\r", sg, lk, len+XUAHEADOFFSET);
					m2ua_asciout_proc(m2ua_ascitemp_buf);
					m2ua_hex_to_ascii((BYTE *)data_ptr, len+XUAHEADOFFSET, m2ua_ascitemp_buf);
					m2ua_asciout_proc(m2ua_ascitemp_buf);
					m2ua_asciout_proc("\n\r");
				}
			}			
			if (m2ua_para.lk_para[lk].enable == 0)
				return -1;
			if (m2ua_para.sg_para[sg].enable == 0)
				return -1;			
			if (m2ua_lk_info[lk].lk_st == M2UA_LK_UP)
			{
				err[2]++;
				if (len <= (M2UA_MAX_MSG_LEN - XUAHEADOFFSET))
				{
					m2ua_sg_info[sg].iid 		= lk;
					m2ua_sg_info[sg].msg		= (BYTE *)data_ptr - RESERVE_FOR_M2UAHEAD;
					m2ua_sg_info[sg].msg_len	= len;
					m2ua_send_msg(sg, M2UA_MAUP_DATA);
					err[4]++;
					return 0;
				}
			}
			break;
		}
		default:
			return -1;
	}
	return -1;
}

int get_m3ua_msg(xua_up_msg_t **data_ptr)
{
	xua_up_msg_t 	*up_ptr;
	BYTE					lk;
	int 					len;
	BYTE					*xua_msg_sd;
	WORD					sg, *xua_sd_h, *xua_sd_t;
	
	if(data_ptr == NULL)
		return -1;	
	
	xua_msg_sd = m3ua_mtp3_sd;
	xua_sd_t = &m3ua_mtp3_sd_t;
	xua_sd_h = &m3ua_mtp3_sd_h;
	
	if (*xua_sd_t == *xua_sd_h)
		return -1;
	
	up_ptr 	= (xua_up_msg_t *)(xua_msg_sd + x256[*xua_sd_t]);
	*xua_sd_t = (*xua_sd_t + 1) & M2UA_MAX_M3MSG_NUM_1;
	
	
	lk 		= up_ptr->msg.m3ua.link;
	sg 		= m2ua_para.lk_para[lk].lk_sg;
	if(up_ptr->msg_class == M3UA_MAUP_MSG)
			len		= ntohs(up_ptr->msg.m3ua.len)+XUAHEADOFFSET;
	else
			len		= 9;
	
	*data_ptr = up_ptr;
	
	if ((moniter_fg & MONITOR_MTP3) == MONITOR_MTP3)
	{
		if ((m2ua_sg_mon_fg[sg] == 1))
		{
			sprintf(m2ua_ascitemp_buf, "Send MSG to MTP3-User, sg=%d, lk=%d, len=%d\n\r", sg, lk, len);
			m2ua_asciout_proc(m2ua_ascitemp_buf);
			m2ua_hex_to_ascii((BYTE *)up_ptr, len, m2ua_ascitemp_buf);
			m2ua_asciout_proc(m2ua_ascitemp_buf);
			m2ua_asciout_proc("\n\r");
		}
	}
	return 0;
}

int put_m3ua_msg(xua_up_msg_t *data_ptr)
{
	BYTE lk;
	int 	len;
	WORD	sg;
	if(data_ptr == NULL)
		return -1;
		
	switch (data_ptr->msg_class)
	{
		case M3UA_MGMT_CMD:
		{
			lk  = data_ptr->msg.lm_lk.link;
			sg 	= m2ua_para.lk_para[lk].lk_sg;
			if ((m2ua_para.sg_para[sg].xUA_ack>>1) != M3UA_APP)
			{	
				m2ua_log_err(sg, "ERROR: SG type is not m3ua!");
				return -1;
			}
			
			len	= 7;

			err[0]++;
			if ((moniter_fg & MONITOR_MTP3) == MONITOR_MTP3)
			{
				if ((m2ua_sg_mon_fg[sg] == 1))
				{
					sprintf(m2ua_ascitemp_buf, "Recv MSG from Mtp3-User, sg=%d, lk=%d, len=%d\n\r", sg, lk, len);
					m2ua_asciout_proc(m2ua_ascitemp_buf);
					m2ua_hex_to_ascii((BYTE *)data_ptr, len, m2ua_ascitemp_buf);
					m2ua_asciout_proc(m2ua_ascitemp_buf);
					m2ua_asciout_proc("\n\r");
				}
			}
			
			if (m2ua_para.lk_para[lk].enable == 0)
				return -1;
			if (m2ua_para.sg_para[sg].enable == 0)
				return -1;			

			if ((data_ptr->msg.lm_lk.opercode == xUA_ENABLE_xUA_LINK) && 
				(!m2ua_lk_info[lk].enable))
			{
				if (enable_sg(sg) < 0)
					return -1;
				
				m2ua_lk_init(lk);
				m2ua_lk_info[lk].enable = 1;
				m2ua_sg_info[sg].act_lks++;
			}
			else if ((data_ptr->msg.lm_lk.opercode == xUA_STOP_xUA_LINK) &&
				m2ua_lk_info[lk].enable)
			{
				if (m2ua_sg_info[sg].m2ua_state == 3)
				{
					m2ua_sg_info[sg].iid 		= lk;
					m2ua_sg_info[sg].mgmt_cmd 	= COMBO_W(data_ptr->msg_class,M2UA_MGMT_CMD_LK_LOCK);
					m2ua_fsm(sg);
				}
				
				rm_sg_lk(sg, lk);
				m2ua_lk_init(lk);
				
				m2ua_lk_info[lk].enable = 0;
			}
			else if ((m2ua_sg_info[sg].m2ua_state == 3) && m2ua_lk_info[lk].enable)
			{
				m2ua_sg_info[sg].mtp3_cmd 	= COMBO_W(data_ptr->msg_class,data_ptr->msg.lm_lk.opercode);
				m2ua_sg_info[sg].iid 		= lk;
				m2ua_fsm(sg);
			}
			return 0;
		}
		case M3UA_MAUP_MSG:
		{
			lk 	= data_ptr->msg.m3ua.link;
			sg 	= m2ua_para.lk_para[lk].lk_sg;			
			len	= ntohs(data_ptr->msg.m3ua.len);
			if ((m2ua_para.sg_para[sg].xUA_ack>>1) != M3UA_APP)
			{	
				m2ua_log_err(sg, "ERROR: SG type is not m3ua!");
				return -1;
			}
			err[0]++;
			if ((moniter_fg & MONITOR_MTP3) == MONITOR_MTP3)
			{
				if ((m2ua_sg_mon_fg[sg] == 1))
				{
					sprintf(m2ua_ascitemp_buf, "Recv MSG from Mtp3-User, sg=%d, lk=%d, len=%d\n\r", sg, lk, len+20);
					m2ua_asciout_proc(m2ua_ascitemp_buf);
					m2ua_hex_to_ascii((BYTE *)data_ptr, len+20, m2ua_ascitemp_buf);
					m2ua_asciout_proc(m2ua_ascitemp_buf);
					m2ua_asciout_proc("\n\r");
				}
			}
			if (m2ua_para.lk_para[lk].enable == 0)
				return -1;
			if (m2ua_para.sg_para[sg].enable == 0)
				return -1;			
			if (m2ua_lk_info[lk].lk_st == M2UA_LK_UP)
			{
				if (len <= (M2UA_MAX_MSG_LEN - XUAHEADOFFSET))
				{
					DWORD pc;
					pc	=	ntohl(data_ptr->msg.m3ua.opc);
					data_ptr->msg.m3ua.opc	=	pc;
					pc	=	ntohl(data_ptr->msg.m3ua.dpc);
					data_ptr->msg.m3ua.dpc	=	pc;
					m2ua_sg_info[sg].iid 		= lk;
					m2ua_sg_info[sg].rc			=	data_ptr->msg.m3ua.rc;
					m2ua_sg_info[sg].msg		= (BYTE *)data_ptr - RESERVE_FOR_M3UAHEAD;
					m2ua_sg_info[sg].msg_len	= len;
					m2ua_send_msg(sg, M3UA_MAUP_DATA);
					return 0;
				}
			}
			break;
		}
		case M3UA_RC_CMD:
		{
			lk  = data_ptr->msg.rc_cmd.link;
			sg 	= m2ua_para.lk_para[lk].lk_sg;
			len	= 9;
			if ((m2ua_para.sg_para[sg].xUA_ack>>1) != M3UA_APP)
			{	
				m2ua_log_err(sg, "ERROR: SG type is not m3ua!");
				return -1;
			}
			err[0]++;
			if ((moniter_fg & MONITOR_MTP3) == MONITOR_MTP3)
			{
				if ((m2ua_sg_mon_fg[sg] == 1))
				{
					sprintf(m2ua_ascitemp_buf, "Recv MSG from Mtp3-User, sg=%d, lk=%d, len=%d\n\r", sg, lk, len);
					m2ua_asciout_proc(m2ua_ascitemp_buf);
					m2ua_hex_to_ascii((BYTE *)data_ptr, len, m2ua_ascitemp_buf);
					m2ua_asciout_proc(m2ua_ascitemp_buf);
					m2ua_asciout_proc("\n\r");
				}
			}
			
			if (m2ua_para.lk_para[lk].enable == 0)
				return -1;
			if (m2ua_para.sg_para[sg].enable == 0)
				return -1;

			if ((m2ua_sg_info[sg].m2ua_state == 3) && m2ua_lk_info[lk].enable)
			{
				m2ua_sg_info[sg].mtp3_cmd 	= COMBO_W(data_ptr->msg_class,data_ptr->msg.rc_cmd.opercode);
				m2ua_sg_info[sg].iid 		= lk;
				m2ua_sg_info[sg].rc 		= data_ptr->msg.m3ua.rc;
				m2ua_fsm(sg);
			}
			return 0;
		}
		default:
			return -1;
	}
	return -1;
}

int set_m2ua_link(BYTE link, BYTE *data_ptr)
{
	BYTE			len;
	WORD			sg;
	m2ua_lk_pro_t 	*m2ua_lk_pro = (m2ua_lk_pro_t *)data_ptr;
	lk_para_t		*lk_ptr;
	
	lk_ptr = (lk_para_t *) &m2ua_para.lk_para[link];
	sg = lk_ptr->lk_sg;
	len	= sizeof(m2ua_lk_pro_t);
	
	if ((moniter_fg & MONITOR_MTP3) == MONITOR_MTP3)
	{
		if ((m2ua_sg_mon_fg[sg] == 1) || (m2ua_lk_mon_fg[link] == 1))
		{
			sprintf(m2ua_ascitemp_buf, "Recv MTP3 Set Link Attributes, sg=%d, lk=%d, len=%d\n\r", sg, link, len);
			m2ua_asciout_proc(m2ua_ascitemp_buf);
			m2ua_hex_to_ascii((BYTE *)m2ua_lk_pro, len, m2ua_ascitemp_buf);
			m2ua_asciout_proc(m2ua_ascitemp_buf);
			m2ua_asciout_proc("\n\r");
		}
	}
	
	/*
	if (init_flag < 2)
	{
		lk_ptr->enable 	= (m2ua_lk_pro->e1_lk_type >> 1) & 0x01;
		lk_ptr->lk_sg 	= m2ua_lk_pro->e1_to_sg;
		lk_ptr->iid		= m2ua_lk_pro->e1_to_iid;
		if (link == 255)
			init_flag++;
	}
	else
	*/
	{
		if (lk_ptr->enable)
		{
			if (m2ua_lk_pro->e1_lk_type & 0x01)		// Bit 0: Link enable status, 0/1=disable/enable
				return -1;
			//else if (m2ua_lk_pro->e1_to_sg != sg)
				//return -1;
		}
		
		/*
		if (m2ua_lk_pro->e1_to_sg != sg)
		{
			if (!((m2ua_para.sg_para[sg].enable == 0) &&
				(m2ua_para.sg_para[m2ua_lk_pro->e1_to_sg].enable == 0))) 
				return -1;
			if (((m2ua_lk_pro->e1_lk_type & 0x07) == 0x03) 			&&	// SIGTRAN | ENABLE | NOT MTP3LITE
				((m2ua_lk_pro->e1_to_mtp3 == host_ip)				||
				(m2ua_lk_pro->e1_to_alterMTP3 == host_ip))			&&
				(m2ua_lk_pro->e1_to_linkset < M2UA_MTP3_MAX_LS_NUM))
			{
				lk_ptr->enable 	= (m2ua_lk_pro->e1_lk_type >> 1) & 0x01;
				lk_ptr->lk_sg 	= m2ua_lk_pro->e1_to_sg;
				lk_ptr->iid		= m2ua_lk_pro->e1_to_iid;
			}
			if (m2ua_lk_info[link].enable == 1)
			{
				rm_sg_lk(sg, link);
				m2ua_lk_info[link].enable = 0;
			}
		}
		else
		{
			if (((m2ua_lk_pro->e1_lk_type & 0x07) == 0x03) 			&&	// SIGTRAN | ENABLE | NOT MTP3LITE
				((m2ua_lk_pro->e1_to_mtp3 == host_ip)				||
				(m2ua_lk_pro->e1_to_alterMTP3 == host_ip))			&&
				(m2ua_lk_pro->e1_to_linkset < M2UA_MTP3_MAX_LS_NUM))
			{
				lk_ptr->enable 	= (m2ua_lk_pro->e1_lk_type >> 1) & 0x01;
				lk_ptr->lk_sg 	= m2ua_lk_pro->e1_to_sg;
				lk_ptr->iid		= m2ua_lk_pro->e1_to_iid;
			}
		}
		*/
	}
	
	sg = lk_ptr->lk_sg;

	if (m2ua_lk_info[link].enable == 0)
	{
		if ((((m2ua_lk_pro->e1_lk_type & 0x0F) == 0x03 || (m2ua_lk_pro->e1_lk_type & 0x0F) == 0x09) &&	// M2UA|M3UA | ENABLE   
			   ((m2ua_lk_pro->e1_to_mtp3 == host_ip)||(m2ua_lk_pro->e1_to_alterMTP3 == host_ip))				&&
			   (m2ua_lk_pro->e1_to_linkset < M2UA_MTP3_MAX_LS_NUM)) 
			  || ((m2ua_lk_pro->e1_lk_type & 0x0F) == 0x07))		//No ss7 | ENABLE
		{
			// Bit 1-3: Link type, 0/1/2/3/4: non-sigtran/sigtran-m2ua/mtp3lite/iua/sigtran-m3ua
			lk_ptr->enable 	= 1;		
			lk_ptr->iid		= m2ua_lk_pro->e1_to_iid;
			lk_ptr->dlci	= 0;
					
			if(link < 128)
				lk_ptr->lk_sg 	= m2ua_lk_pro->e1_to_sg;
			else
				lk_ptr->lk_sg 	= m2ua_lk_pro->e1_to_sg + M2UA_MAX_SG_NUM/2;
				
			if((m2ua_lk_pro->e1_lk_type & 0x0F) == 0x09)	//m3ua
				lk_ptr->lk_sg 	= m2ua_lk_pro->e1_to_sg;
			//if (enable_sg(sg) < 0)
				//return -1;
			
			m2ua_lk_init(link);
			//m2ua_lk_info[link].enable = 1;
			//m2ua_sg_info[sg].act_lks++;
		}
		else if (lk_ptr->enable)
		{
			lk_ptr->enable 	= 0;
			lk_ptr->lk_sg 	= 0;
			lk_ptr->iid		= 0;
			lk_ptr->dlci	= 0;
		}
	}
	else
	{
		if ((((m2ua_lk_pro->e1_lk_type & 0x0F) != 0x03 || (m2ua_lk_pro->e1_lk_type & 0x0F) != 0x09) ||
			   ((m2ua_lk_pro->e1_to_mtp3 != host_ip)	&& (m2ua_lk_pro->e1_to_alterMTP3 != host_ip))					 ||
			   (m2ua_lk_pro->e1_to_linkset >= M2UA_MTP3_MAX_LS_NUM))
			 && ((m2ua_lk_pro->e1_lk_type & 0x0F) != 0x07))
		{
			if (m2ua_sg_info[sg].m2ua_state == 3)
			{
				m2ua_sg_info[sg].iid 		= link;
				m2ua_sg_info[sg].mgmt_cmd 	= M2UA_MGMT_CMD_LK_LOCK;
				m2ua_fsm(sg);
			}
			
			rm_sg_lk(sg, link);
			m2ua_lk_init(link);
			
			lk_ptr->enable 	= 0;
			lk_ptr->lk_sg 	= 0;
			lk_ptr->iid		= 0;
			lk_ptr->dlci	= 0;
		}
	}
	
	return len;
}

int set_m2ua_sg(WORD sg, BYTE *data_ptr)
{
	BYTE			len;
	sg_para_t		*sg_ptr;
	
	len	= sizeof(sg_para_t);
	
	if ((moniter_fg & MONITOR_MTP3) == MONITOR_MTP3)
	{
		if (m2ua_sg_mon_fg[sg] == 1)
		{
			sprintf(m2ua_ascitemp_buf, "Recv MTP3 Set SG Attributes, sg=%d, len=%d\n\r", sg, len);
			m2ua_asciout_proc(m2ua_ascitemp_buf);
			m2ua_hex_to_ascii(data_ptr, len, m2ua_ascitemp_buf);
			m2ua_asciout_proc(m2ua_ascitemp_buf);
			m2ua_asciout_proc("\n\r");
		}
	}
	
	/*
	if (init_flag < 2)
	{
		bcopy(data_ptr, (BYTE *) &m2ua_para.sg_para[sg], len);
		if (sg == 255)
			init_flag++;
	}
	else
	*/
	{
		sg_ptr = (sg_para_t *) data_ptr;
		
		if (m2ua_para.sg_para[sg].enable && 
			m2ua_para.sg_para[sg+M2UA_MAX_SG_NUM/2].enable)
		{
			if (sg_ptr->enable)
				return -1;
//			else if ((sg_ptr->server != m2ua_para.sg_para[sg].server) ||
//				(sg_ptr->ip != m2ua_para.sg_para[sg].ip))
			else
			{				
				if (((m2ua_sg_info[sg].enable == 0) ||(m2ua_sg_info[sg].fd == 0)) &&
					!((m2ua_sg_info[sg].sctp_state == 3) && (m2ua_sg_info[sg].sctp_state_1 == 1)))	// Not Client at sctp 3-1 state
					m2ua_para.sg_para[sg].enable = 0;
				else
					m2ua_para.sg_para[sg].enable = 2;
				
				sg = sg + M2UA_MAX_SG_NUM/2;
				if (((m2ua_sg_info[sg].enable == 0) ||(m2ua_sg_info[sg].fd == 0)) &&
					!((m2ua_sg_info[sg].sctp_state == 3) && (m2ua_sg_info[sg].sctp_state_1 == 1)))	// Not Client at sctp 3-1 state
					m2ua_para.sg_para[sg].enable = 0;
				else
					m2ua_para.sg_para[sg].enable = 2;					
				return len;
			}
		}
		
		/*
		if ((sg_ptr->server != m2ua_para.sg_para[sg].server) ||
			(sg_ptr->ip != m2ua_para.sg_para[sg].ip))
			m2ua_para.sg_para[sg].enable = 2;
		else if (sg_ptr->enable >= 1)
			m2ua_para.sg_para[sg].enable = 1;
		else
			m2ua_para.sg_para[sg].enable = 0;
		bcopy(data_ptr + 1, (BYTE *) &m2ua_para.sg_para[sg] + 1, len - 1);
		*/
		
		bcopy(data_ptr, (BYTE *) &m2ua_para.sg_para[sg], len);
		if ((m2ua_para.sg_para[sg].xUA_ack>>1) == M2UA_APP)
			m2ua_para.sg_para[sg].plat_port[0]	=	M2UA_PORT_0;
		else if ((m2ua_para.sg_para[sg].xUA_ack>>1) == IUA_APP)
			m2ua_para.sg_para[sg].plat_port[0]	=	IUA_PORT_0;
		else if ((m2ua_para.sg_para[sg].xUA_ack>>1) == M3UA_APP)			
			m2ua_para.sg_para[sg].plat_port[0]	=	M3UA_PORT_0;
		
		sg = sg + M2UA_MAX_SG_NUM/2;
		bcopy(data_ptr, (BYTE *) &m2ua_para.sg_para[sg], len);
		if ((m2ua_para.sg_para[sg].xUA_ack>>1) == M2UA_APP)
			m2ua_para.sg_para[sg].plat_port[0]	=	M2UA_PORT_1;
		else if ((m2ua_para.sg_para[sg].xUA_ack>>1) == IUA_APP)
			m2ua_para.sg_para[sg].plat_port[0]	=	IUA_PORT_1;		
		else if ((m2ua_para.sg_para[sg].xUA_ack>>1) == M3UA_APP)			
			m2ua_para.sg_para[sg].plat_port[0]	=	M3UA_PORT_1;		
	}
	m2ua_para.sg_para[sg].plat_port[1]	=	0;		
	return len;
}

int m2ua_sctp_close(int fd, WORD sg_id)
{
	int ret;
	
	if ((ret = close(fd)) < 0)
		m2ua_log_err(sg_id, "ERROR: M2UA SCTP close!");
	
	return ret;
}

#ifndef _LKSCTP

int m2ua_sctp_get_msg(int fd, WORD sg)
{
	int		ret;
	int 	flags = 0;
	BYTE	err_text[128];
	//BYTE	in_b;
	
	m2ua_sctp_data.buf = m2ua_sctp_dat;
	
	//in_b = inb(0x378);
	//outb(in_b | 0x02, 0x378);
	//20 us
	
	while ((ret = getmsg(fd, &m2ua_sctp_ctrl, &m2ua_sctp_data, &flags)) < 0)
	{
		switch (errno)
		{
			default:
			case EPROTO:
			case EINVAL:
				sprintf(err_text, "ERROR: M2UA SCTP getmsg: [%d] %s", errno, strerror(errno));
				m2ua_log_err(sg, err_text);
			case EINTR:
			case ERESTART:
				continue;
			case EAGAIN:
				break;
		}
		break;
	}
	
	//outb(in_b & 0xFD, 0x378);
	
	if (!ret)
		return (m2ua_sctp_cmd.tpi.type);
	else
		return (-1);
}

char *dec_sctp_primi(long sctp_primi)
{
	switch (sctp_primi)
	{
		case T_CONN_REQ:		return("T_CONN_REQ");
		case T_CONN_RES:		return("T_CONN_RES");
		case T_DISCON_REQ:		return("T_DISCON_REQ");
		case T_DATA_REQ:		return("T_DATA_REQ");
		case T_EXDATA_REQ:		return("T_EXDATA_REQ");
		case T_OPTDATA_REQ:		return("T_OPTDATA_REQ");
		case T_INFO_REQ:		return("T_INFO_REQ");
		case T_BIND_REQ:		return("T_BIND_REQ");
		case T_UNBIND_REQ:		return("T_UNBIND_REQ");
		case T_UNITDATA_REQ:	return("T_UNITDATA_REQ");
		case T_OPTMGMT_REQ:		return("T_OPTMGMT_REQ");
		case T_ORDREL_REQ:		return("T_ORDREL_REQ");
		case T_CONN_IND:		return("T_CONN_IND");
		case T_CONN_CON:		return("T_CONN_CON");
		case T_DISCON_IND:		return("T_DISCON_IND");
		case T_DATA_IND:		return("T_DATA_IND");
		case T_EXDATA_IND:		return("T_EXDATA_IND");
		case T_OPTDATA_IND:		return("T_OPTDATA_IND");
		case T_INFO_ACK:		return("T_INFO_ACK");
		case T_BIND_ACK:		return("T_BIND_ACK");
		case T_ERROR_ACK:		return("T_ERROR_ACK");
		case T_OK_ACK:			return("T_OK_ACK");
		case T_UNITDATA_IND:	return("T_UNITDATA_IND");
		case T_UDERROR_IND:		return("T_UDERROR_IND");
		case T_OPTMGMT_ACK:		return("T_OPTMGMT_ACK");
		case T_ORDREL_IND:		return("T_ORDREL_IND");
		case T_ADDR_REQ:		return("T_ADDR_REQ");
		case T_ADDR_ACK:		return("T_ADDR_ACK");
		default:				return("Unexpected");
	}
}

char *dec_sctp_err(long sctp_err)
{
	switch (sctp_err)
	{
		case TBADADDR:			return("TBADADDR");
		case TBADOPT:			return("TBADOPT");
		case TACCES:			return("TACCES");
		case TBADF:				return("TBADF");
		case TNOADDR:			return("TNOADDR");
		case TOUTSTATE:			return("TOUTSTATE");
		case TBADSEQ:			return("TBADSEQ");
		case TSYSERR:			return("TSYSERR");
		case TLOOK:				return("TLOOK");
		case TBADDATA:			return("TBADDATA");
		case TBUFOVFLW:			return("TBUFOVFLW");
		case TFLOW:				return("TFLOW");
		case TNODATA:			return("TNODATA");
		case TNODIS:			return("TNODIS");
		case TNOUDERR:			return("TNOUDERR");
		case TBADFLAG:			return("TBADFLAG");
		case TNOREL:			return("TNOREL");
		case TNOTSUPPORT:		return("TNOTSUPPORT");
		case TSTATECHNG:		return("TSTATECHNG");
		case TNOSTRUCTYPE:		return("TNOSTRUCTTYPE");
		case TBADNAME:			return("TBADNAME");
		case TBADQLEN:			return("TBADQLEN");
		case TADDRBUSY:			return("TADDRBUSY");
		case TINDOUT:			return("TINDOUT");
		case TPROVMISMATCH:		return("TPROVMISMATCH");
		case TRESQLEN:			return("TRESQLEN");
		case TRESADDR:			return("TRESADDR");
		case TQFULL:			return("TQFULL");
		case TPROTO:			return("TPROTO");
		default:				return("(unknown)");
	}
}

int expect(int fd, int sg, int *msg, int want)
{
	int got;
	
	got 	= m2ua_sctp_get_msg(fd, sg);
	*msg 	= got;
	
	if (got >= 0)
	{
		if ((moniter_fg & MONITOR_SCTP) == MONITOR_SCTP)
		{
			if (m2ua_sg_mon_fg[sg] == 1)
			{
				sprintf(m2ua_ascitemp_buf, "Recv %s from SCTP, sg=%d, ctrl len=%d\n\r", dec_sctp_primi(m2ua_sctp_cmd.tpi.type), sg, m2ua_sctp_ctrl.len);
				m2ua_asciout_proc(m2ua_ascitemp_buf);
				if (m2ua_sctp_cmd.tpi.type == T_ERROR_ACK)
				{
					sprintf(m2ua_ascitemp_buf, "Error Code: %s\n\r", dec_sctp_err(m2ua_sctp_cmd.tpi.error_ack.TLI_error));
					m2ua_asciout_proc(m2ua_ascitemp_buf);
				}
				m2ua_hex_to_ascii(m2ua_sctp_cmd.cbuf, m2ua_sctp_ctrl.len, m2ua_ascitemp_buf);
				m2ua_asciout_proc(m2ua_ascitemp_buf);
				m2ua_asciout_proc("\n\r");
			}
		}
		
		if (m2ua_sctp_data.len > 0)
		{
			if ((moniter_fg & MONITOR_SCTP) == MONITOR_SCTP)
			{
				if (m2ua_sg_mon_fg[sg] == 1)
				{
					sprintf(m2ua_ascitemp_buf, "Data len=%d\n\r", m2ua_sctp_data.len);
					m2ua_asciout_proc(m2ua_ascitemp_buf);
					m2ua_hex_to_ascii(m2ua_sctp_dat, m2ua_sctp_data.len, m2ua_ascitemp_buf);
					m2ua_asciout_proc(m2ua_ascitemp_buf);
					m2ua_asciout_proc("\n\r");
				}
			}
		}
	}
	
	if (got == want)
		return M2UA_SUCCESS;
	else
		return M2UA_FAILURE;
}

int m2ua_sctp_put_msg(int fd, int sg)
{
	int 	ret;
	struct 	strbuf *mydata = m2ua_sctp_data.len ? &m2ua_sctp_data : NULL;
	BYTE	err_text[128];
	//BYTE	in_b;
	
	if ((moniter_fg & MONITOR_SCTP) == MONITOR_SCTP)
	{
		if (m2ua_sg_mon_fg[sg] == 1)
		{
			sprintf(m2ua_ascitemp_buf, "Send %s to SCTP, sg=%d, ctrl len=%d\n\r", dec_sctp_primi(m2ua_sctp_cmd.tpi.type), sg, m2ua_sctp_ctrl.len);
			m2ua_asciout_proc(m2ua_ascitemp_buf);
			m2ua_hex_to_ascii(m2ua_sctp_cmd.cbuf, m2ua_sctp_ctrl.len, m2ua_ascitemp_buf);
			m2ua_asciout_proc(m2ua_ascitemp_buf);
			m2ua_asciout_proc("\n\r");
		
			if (m2ua_sctp_data.len > 0)
			{
				sprintf(m2ua_ascitemp_buf, "Data len=%d\n\r", m2ua_sctp_data.len);
				m2ua_asciout_proc(m2ua_ascitemp_buf);
				m2ua_hex_to_ascii(m2ua_sctp_data.buf, m2ua_sctp_data.len, m2ua_ascitemp_buf);
				m2ua_asciout_proc(m2ua_ascitemp_buf);
				m2ua_asciout_proc("\n\r");
			}
		}
	}
	
	//in_b = inb(0x378);
	//outb(in_b | 0x04, 0x378);
	//88 us
	
	while ((ret = putpmsg(fd, &m2ua_sctp_ctrl, mydata, 0, MSG_HIPRI)) < 0)
	{
		switch (errno) 
		{
			default:
				sprintf(err_text, "ERROR: M2UA SCTP putpmsg: [%d] %s", errno, strerror(errno));
				m2ua_log_err(sg, err_text);
				break;
			case EINTR:
			case ERESTART:
				continue;
			case EAGAIN:
				printf("m2ua put msg EAGAIN\n");
				break;
		}
		break;
	}
	
	//outb(in_b & 0xFB, 0x378);
	
	if (!ret)
		return(0);
	else
		return(-1);
}

int m2ua_sctp_put_fdi(int fd, int fd2, int sg, int offset, int flags)
{
	BYTE err_text[256];
	
	m2ua_sctp_fdi.flags  = flags;
	m2ua_sctp_fdi.fildes = fd2;
	m2ua_sctp_fdi.offset = offset;
	
	if ((moniter_fg & MONITOR_SCTP) == MONITOR_SCTP)
	{
		if (m2ua_sg_mon_fg[sg] == 1)
		{
			sprintf(m2ua_ascitemp_buf, "Send %s to SCTP, sg=%d, ctrl len=%d\n\r", dec_sctp_primi(m2ua_sctp_cmd.tpi.type), sg, m2ua_sctp_ctrl.len);
			m2ua_asciout_proc(m2ua_ascitemp_buf);
			m2ua_hex_to_ascii(m2ua_sctp_cmd.cbuf, m2ua_sctp_ctrl.len, m2ua_ascitemp_buf);
			m2ua_asciout_proc(m2ua_ascitemp_buf);
			m2ua_asciout_proc("\n\r");
		}
	}
	
	if (ioctl(fd, I_FDINSERT, &m2ua_sctp_fdi) < 0)
	{
		sprintf(err_text, "ERROR: M2UA SCTP ioctl: [%d] %s", errno, strerror(errno));
		m2ua_log_err(sg, err_text);
	}
	
	return(0);
}

int m2ua_sctp_t_open(WORD sg)
{
	int fd;
	
	if ((fd = open("/dev/sctp_t",O_NONBLOCK|O_RDWR)) < 0)
		m2ua_log_err(sg, "ERROR: M2UA SCTP open");
	
	return fd;
}

int m2ua_sctp_optmgmt_req(int fd, int sg, DWORD flags)
{
	m2ua_sctp_data.len = 0;
	m2ua_sctp_ctrl.len = sizeof(m2ua_sctp_cmd.tpi.optmgmt_req) + sizeof(m2ua_sctp_opt_optm);
	m2ua_sctp_cmd.tpi.type = T_OPTMGMT_REQ;
	m2ua_sctp_cmd.tpi.optmgmt_req.MGMT_flags = flags;
	m2ua_sctp_cmd.tpi.optmgmt_req.OPT_length = sizeof(m2ua_sctp_opt_optm);
	m2ua_sctp_cmd.tpi.optmgmt_req.OPT_offset = sizeof(m2ua_sctp_cmd.tpi.optmgmt_req);

	m2ua_sctp_opt_optm.ppi_val = m2ua_para.sg_para[sg].xUA_ack>>1;
	bcopy(&m2ua_sctp_opt_optm, (m2ua_sctp_cmd.cbuf + sizeof(m2ua_sctp_cmd.tpi.optmgmt_req)), sizeof(m2ua_sctp_opt_optm));
	return m2ua_sctp_put_msg(fd, sg);
}

int m2ua_sctp_bind_req(int fd, int sg, m2ua_sctp_addr_t *addr, int coninds)
{
	m2ua_sctp_data.len = 0;
	m2ua_sctp_ctrl.len = sizeof(m2ua_sctp_cmd.tpi.bind_req) + sizeof(*addr);
	m2ua_sctp_cmd.tpi.type = T_BIND_REQ;
	m2ua_sctp_cmd.tpi.bind_req.ADDR_length = sizeof(*addr);
	m2ua_sctp_cmd.tpi.bind_req.ADDR_offset = sizeof(m2ua_sctp_cmd.tpi.bind_req);
	m2ua_sctp_cmd.tpi.bind_req.CONIND_number = coninds;
	bcopy(addr, (&m2ua_sctp_cmd.tpi.bind_req) + 1, sizeof(*addr));
	return m2ua_sctp_put_msg(fd, sg);
}

int m2ua_sctp_conn_req(int fd, int sg, m2ua_sctp_addr_t *addr)
{
	m2ua_sctp_data.len = 0;
	m2ua_sctp_ctrl.len = sizeof(m2ua_sctp_cmd.tpi.conn_req)+sizeof(*addr);
	m2ua_sctp_cmd.tpi.type = T_CONN_REQ;
	m2ua_sctp_cmd.tpi.conn_req.DEST_length = sizeof(*addr);
	m2ua_sctp_cmd.tpi.conn_req.DEST_offset = sizeof(m2ua_sctp_cmd.tpi.conn_req);
	m2ua_sctp_cmd.tpi.conn_req.OPT_length = 0;
	m2ua_sctp_cmd.tpi.conn_req.OPT_offset = sizeof(m2ua_sctp_cmd.tpi.conn_req)+sizeof(*addr);
	bcopy(addr, (m2ua_sctp_cmd.cbuf + sizeof(m2ua_sctp_cmd.tpi.conn_req)), sizeof(*addr));
	return m2ua_sctp_put_msg(fd, sg);
}

int m2ua_sctp_conn_res(int fd, int fd2, int sg, long seq)
{
	m2ua_sctp_fdi.databuf.len = 0;
	m2ua_sctp_fdi.ctlbuf.len = sizeof(m2ua_sctp_cmd.tpi.conn_res);
	m2ua_sctp_cmd.tpi.type = T_CONN_RES;
	m2ua_sctp_cmd.tpi.conn_res.ACCEPTOR_id = 0;
	m2ua_sctp_cmd.tpi.conn_res.SEQ_number = seq;
	m2ua_sctp_cmd.tpi.conn_res.OPT_offset = 0;
	m2ua_sctp_cmd.tpi.conn_res.OPT_length = 0;
	return m2ua_sctp_put_fdi(fd, fd2, sg, 4, 0);
}

int m2ua_sctp_discon_req(int fd, int sg, DWORD seq)
{
	m2ua_sctp_data.len = 0;
	m2ua_sctp_ctrl.len = sizeof(m2ua_sctp_cmd.tpi.discon_req);
	m2ua_sctp_cmd.tpi.type = T_DISCON_REQ;
	m2ua_sctp_cmd.tpi.discon_req.SEQ_number = seq;
	return m2ua_sctp_put_msg(fd, sg);
}

int m2ua_sctp_ordrel_req(int fd, int sg)
{
	m2ua_sctp_data.len = 0;
	m2ua_sctp_ctrl.len = sizeof(m2ua_sctp_cmd.tpi.ordrel_req);
	m2ua_sctp_cmd.tpi.type = T_ORDREL_REQ;
	return m2ua_sctp_put_msg(fd, sg);
}

int m2ua_sctp_optdata_req(int fd, int sg, int len)
{
	if (!len)
		return (-1);
	else
		m2ua_sctp_data.len = len;
	
	m2ua_sctp_ctrl.len = sizeof(m2ua_sctp_cmd.tpi.optdata_req) + sizeof(m2ua_sctp_opt_data);
	m2ua_sctp_cmd.tpi.type = T_OPTDATA_REQ;
	m2ua_sctp_cmd.tpi.optdata_req.DATA_flag = 0;
	m2ua_sctp_cmd.tpi.optdata_req.OPT_length = sizeof(m2ua_sctp_opt_data);
	m2ua_sctp_cmd.tpi.optdata_req.OPT_offset = sizeof(m2ua_sctp_cmd.tpi.optdata_req);
	bcopy(&m2ua_sctp_opt_data, m2ua_sctp_cmd.cbuf + sizeof(m2ua_sctp_cmd.tpi.optdata_req), sizeof(m2ua_sctp_opt_data));
	return m2ua_sctp_put_msg(fd, sg);
}

#else

char *dec_sctp_primi_lksctp(long sctp_primi)
{
	switch (sctp_primi)
	{
		case M2UA_LKSCTP_ASSOC_CHANGE_COMM_UP:			return("M2UA_LKSCTP_ASSOC_CHANGE_COMM_UP");
		case M2UA_LKSCTP_ASSOC_CHANGE_COMM_LOST:		return("M2UA_LKSCTP_ASSOC_CHANGE_COMM_LOST");
		case M2UA_LKSCTP_ASSOC_CHANGE_SHUTDOWN_COMP:	return("M2UA_LKSCTP_ASSOC_CHANGE_SHUTDOWN_COMP");
		case M2UA_LKSCTP_ASSOC_CHANGE_RESTART:			return("M2UA_LKSCTP_ASSOC_CHANGE_RESTART");
		case M2UA_LKSCTP_ASSOC_CHANGE_CANT_STR_ASSOC:	return("M2UA_LKSCTP_ASSOC_CHANGE_CANT_STR_ASSOC");
		case M2UA_LKSCTP_SEND_FAILED:					return("M2UA_LKSCTP_SEND_FAILED");
		case M2UA_LKSCTP_PEER_ADDR_CHANGE:				return("M2UA_LKSCTP_PEER_ADDR_CHANGE");
		case M2UA_LKSCTP_REMOTE_ERROR:					return("M2UA_LKSCTP_REMOTE_ERROR");
		case M2UA_LKSCTP_SHUTDOWN_EVENT:				return("M2UA_LKSCTP_SHUTDOWN_EVENT");
		case M2UA_LKSCTP_DATA_IND:						return("M2UA_LKSCTP_DATA_IND");
		case M2UA_LKSCTP_UNKNOWN_EVENT:					return("M2UA_LKSCTP_UNKNOWN_EVENT");
		default:										return("Unexpected");
	}
}

int m2ua_sctp_optmgmt_req_lksctp(int fd, int sg)
{
	struct linger lg;
	struct sctp_event_subscribe event;
	struct sctp_initmsg initopt;
    struct sctp_rtoinfo rtoinfo;
    struct sctp_assocparams assocparams;
	    
    if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
    {
       	m2ua_log_err(sg, "M2UA set nonblock failure!");
       	return 0;
    }
    
    lg.l_onoff = 1;
    lg.l_linger = 0;
    
    if (setsockopt(fd, SOL_SOCKET, SO_LINGER, &lg, sizeof(lg)) != 0)
	{
         m2ua_log_err(sg, "set linger failed!");
         //return 0;
    }
    
    if ((sg >= M2UA_MAX_SG_NUM) ||
    	((sg < M2UA_MAX_SG_NUM) && !m2ua_para.sg_para[sg].server))
    {
		// Enable all events
	    event.sctp_data_io_event = 1;
	    event.sctp_association_event = 1;
	    event.sctp_address_event = 1;
	    event.sctp_send_failure_event = 1;
	    event.sctp_peer_error_event = 1;
	    event.sctp_shutdown_event = 1;
	    event.sctp_partial_delivery_event = 1;
	    event.sctp_adaptation_layer_event = 1;
	    //event.sctp_adaption_layer_event = 1;
	    
		if (setsockopt(fd, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(event)) != 0)
		{
	         m2ua_log_err(sg, "set event failed!");
	         return 0;
	    }
	    
	    initopt.sinit_num_ostreams = 257;
	    initopt.sinit_max_instreams = 257;
	    initopt.sinit_max_attempts = 8;
	    initopt.sinit_max_init_timeo = 0;
	    
	    if (setsockopt(fd, IPPROTO_SCTP, SCTP_INITMSG, &initopt, sizeof(initopt)) != 0)
		{
	         m2ua_log_err(sg, "set initopt failed!");
	         return 0;
	    }
	    
	    rtoinfo.srto_assoc_id = 0;
	    rtoinfo.srto_initial = 1000;
	    rtoinfo.srto_max = 5000;
	    rtoinfo.srto_min = 1000;
	    
	    if (setsockopt(fd, IPPROTO_SCTP, SCTP_RTOINFO, &rtoinfo, sizeof(rtoinfo)) != 0)
		{
	         m2ua_log_err(sg, "set rtoinfo failed!");
	         //return 0;
	    }
	    
	    memset((BYTE *)&assocparams, 0, sizeof(assocparams));
	    assocparams.sasoc_asocmaxrxt = 5;
	   	if (setsockopt(fd, IPPROTO_SCTP, SCTP_ASSOCINFO, &assocparams, sizeof(assocparams)) != 0)
		{
	         m2ua_log_err(sg, "set assocparams failed!");
	         //return 0;
	    }
    }
    
    if (((moniter_fg & MONITOR_SCTP) == MONITOR_SCTP) &&
		(m2ua_sg_mon_fg[sg] == 1))
	{
		sprintf(m2ua_ascitemp_buf, "m2ua_sctp_optmgmt_req_lksctp succeed, sg=%d, fd=%d\n\r", sg, fd);
		m2ua_asciout_proc(m2ua_ascitemp_buf);
	}
	
    return 1;
}

int m2ua_sctp_optmgmt_req_lksctp_ext(int fd, int sg)
{
    struct sctp_paddrparams paddrparams;
    struct sockaddr_in *paddr;
	
    if (sg < M2UA_MAX_SG_NUM)
    {
	    memset((BYTE *)&paddrparams, 0, sizeof(paddrparams));
	    paddr = (struct sockaddr_in *)&paddrparams.spp_address;
	    paddr->sin_family = AF_INET;
	    if (m2ua_para.sg_para[sg].server)
	    	paddr->sin_port = m2ua_sg_info[sg].rem_port;
	    else
	    {
	    	if ((m2ua_para.sg_para[sg].xUA_ack>>1) == M2UA_APP)	
	    		paddr->sin_port = htons(M2UA_PORT_0);
	    	else if ((m2ua_para.sg_para[sg].xUA_ack>>1) == IUA_APP)	
	    		paddr->sin_port = htons(IUA_PORT_0);	    		
	    	else if ((m2ua_para.sg_para[sg].xUA_ack>>1) == M3UA_APP)	
	    		paddr->sin_port = htons(M3UA_PORT_0);	    		
	    }
	    paddr->sin_addr.s_addr = m2ua_para.sg_para[sg].ip;
	    paddrparams.spp_hbinterval = 20000;
	    paddrparams.spp_pathmaxrxt = 5;
	    
	    if (setsockopt(fd, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, &paddrparams, sizeof(paddrparams)) != 0)
		{
	         m2ua_log_err(sg, "set paddrparams failed!");
	         //return 0;
	    }
	}
	
    if (((moniter_fg & MONITOR_SCTP) == MONITOR_SCTP) &&
		(m2ua_sg_mon_fg[sg] == 1))
	{
		sprintf(m2ua_ascitemp_buf, "m2ua_sctp_optmgmt_req_lksctp_ext succeed, sg=%d, fd=%d\n\r", sg, fd);
		m2ua_asciout_proc(m2ua_ascitemp_buf);
	}
	
    return 1;
}

int m2ua_sctp_bind_req_lksctp(int fd, int sg, m2ua_sctp_addr_t *addr, int coninds)
{
	struct sockaddr_in sin[1];

	sin->sin_family = AF_INET;
	sin->sin_port = addr->port;
	sin->sin_addr.s_addr = addr->addr.s_addr;
	
	if (bind(fd, (struct sockaddr *)sin, sizeof (*sin)) == -1)
	{
        m2ua_log_err(sg, "bind failed!");
        return 0;
	}
	
	if (((moniter_fg & MONITOR_SCTP) == MONITOR_SCTP) &&
		(m2ua_sg_mon_fg[sg] == 1))
	{
		sprintf(m2ua_ascitemp_buf, "m2ua_sctp_bind_req_lksctp succeed, sg=%d, fd=%d\n\r", sg, fd);
		m2ua_asciout_proc(m2ua_ascitemp_buf);
	}
	
	if (coninds)
	{
		if (listen(fd, 1) == -1)
		{
            m2ua_log_err(sg, "listen failed!");
        	return 0;
        }
        if ((moniter_fg & MONITOR_SCTP) == MONITOR_SCTP)
		{
			sprintf(m2ua_ascitemp_buf, "m2ua_sctp_listen_lksctp succeed, sg=%d, fd=%d\n\r", sg, fd);
			m2ua_asciout_proc(m2ua_ascitemp_buf);
		}
    }
    
	return 1;
}

int m2ua_sctp_open_lksctp(WORD sg)
{
	int fd;
	
	if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP)) == -1)
        m2ua_log_err(sg, "M2UA lksctp open failure!");
    
    if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
    {
       	m2ua_log_err(sg, "M2UA set nonblock failure!");
       	return 0;
    }
    
    if (((moniter_fg & MONITOR_SCTP) == MONITOR_SCTP) &&
		(m2ua_sg_mon_fg[sg] == 1))
	{
		sprintf(m2ua_ascitemp_buf, "m2ua_sctp_open_lksctp succeed, sg=%d, fd=%d\n\r", sg, fd);
		m2ua_asciout_proc(m2ua_ascitemp_buf);
	}
	
	return fd;
}

int m2ua_sctp_conn_req_lksctp(int fd, int sg, m2ua_sctp_addr_t *addr)
{
	struct sockaddr_in sin[1];

	sin->sin_family = AF_INET;
	sin->sin_port = addr->port;
	sin->sin_addr.s_addr = addr->addr.s_addr;
	
	connect(fd, (struct sockaddr *)sin, sizeof(sin));
	
	if (((moniter_fg & MONITOR_SCTP) == MONITOR_SCTP) &&
		(m2ua_sg_mon_fg[sg] == 1))
	{
		sprintf(m2ua_ascitemp_buf, "m2ua_sctp_conn_req_lksctp sent, sg=%d, fd=%d\n\r", sg, fd);
		m2ua_asciout_proc(m2ua_ascitemp_buf);
	}
	
	return 0;
}

int m2ua_handle_event_lksctp(void *buf)
{
    struct sctp_assoc_change *sac;
    //struct sctp_send_failed *ssf;
    //struct sctp_paddr_change *spc;
    //struct sctp_remote_error *sre;
    union  sctp_notification *snp;
    //char   addrbuf[8];
    //const  char *ap;
    //struct sockaddr_in *sin;

    snp = buf;

    switch (snp->sn_header.sn_type)
    {
    case SCTP_ASSOC_CHANGE:
        sac = &snp->sn_assoc_change;
        //printf("^^^ assoc_change: state=%hu, error=%hu, instr=%hu "
        //    "outstr=%hu\n", sac->sac_state, sac->sac_error,
        //    sac->sac_inbound_streams, sac->sac_outbound_streams);
        return ((SCTP_ASSOC_CHANGE << 16) | (sac->sac_state & 0xFFFF));
    case SCTP_SEND_FAILED:
        //ssf = &snp->sn_send_failed;
        //printf("^^^ sendfailed: len=%hu err=%d\n", ssf->ssf_length,
        //    ssf->ssf_error);
        return M2UA_LKSCTP_SEND_FAILED;
    case SCTP_PEER_ADDR_CHANGE:
        //spc = &snp->sn_paddr_change;
        //if (spc->spc_aaddr.ss_family == AF_INET) {
        //  sin = (struct sockaddr_in *)&spc->spc_aaddr;
        //  ap = inet_ntop(AF_INET, &sin->sin_addr,
        //                 addrbuf, 8);
        //}
        //printf("^^^ intf_change: %s state=%d, error=%d\n", ap,
        //       spc->spc_state, spc->spc_error);
        return M2UA_LKSCTP_PEER_ADDR_CHANGE;
    case SCTP_REMOTE_ERROR:
        //sre = &snp->sn_remote_error;
        //printf("^^^ remote_error: err=%hu len=%hu\n",
        //    ntohs(sre->sre_error), ntohs(sre->sre_length));
        return M2UA_LKSCTP_REMOTE_ERROR;
    case SCTP_SHUTDOWN_EVENT:
        //printf("^^^ shutdown event\n");
        return M2UA_LKSCTP_SHUTDOWN_EVENT;
    default:
        //printf("unknown type: %hu\n", snp->sn_header.sn_type);
        return M2UA_LKSCTP_UNKNOWN_EVENT;
   }
   
   return -1;
}

void *m2ua_recvmsg_lksctp(WORD sg, int fd, struct msghdr *msg, void *data_buf, int *data_len, int cmsglen)
{
    int 	nr = 0, nnr = 0;
   	struct 	iovec iov[1];
   	//BYTE	tmp_buf[M2UA_SCTP_DAT_BUFSIZE];

   	*data_len = 0;
   	iov->iov_base = data_buf;
   	iov->iov_len = M2UA_SCTP_DAT_BUFSIZE;
   	
   	msg->msg_iov = iov;
   	msg->msg_iovlen = 1;

    //for (;;)
    {
#ifndef MSG_XPG4_2
#define MSG_XPG4_2 0
#endif
        msg->msg_flags = MSG_XPG4_2;
        msg->msg_controllen = cmsglen;

        nnr = recvmsg(fd, msg, 0);
        if (nnr <= 0)
        {
            /* EOF or error */
            *data_len = nr;
            return (NULL);
        }
        nr += nnr;

        if ((msg->msg_flags & MSG_EOR) != 0)
        {
            *data_len = nr;
            return (data_buf);
        }
		
		//iov->iov_base = tmp_buf;
   		//iov->iov_len = M2UA_SCTP_DAT_BUFSIZE;
    }
    
    m2ua_log_err(sg, "m2ua_recvmsg_lksctp MSG_EOR flag not set!");
    
    return (NULL);
}

int m2ua_sctp_get_msg_lksctp(int fd, WORD sg)
{
	int		ret = -1;
	//BYTE	in_b;
    struct 	sctp_sndrcvinfo *sri;
    struct 	msghdr msg[1];
    struct 	cmsghdr *cmsg;
    BYTE	*cbuf;
    BYTE	*dbuf;
    int 	cmsglen = sizeof(*cmsg) + sizeof(*sri);
    
    //in_b = inb(0x378);
	//outb(in_b | 0x02, 0x378);
	
    /* Set up the msghdr structure for receiving */
    memset(msg, 0, sizeof (*msg));
    cbuf = m2ua_sctp_cmd.cbuf;
    dbuf = m2ua_sctp_dat;
    msg->msg_control = cbuf;
    msg->msg_controllen = cmsglen;
    msg->msg_flags = 0;
    cmsg = (struct cmsghdr *)cbuf;
    sri = (struct sctp_sndrcvinfo *)(cmsg + 1);
	m2ua_sctp_dat_len = M2UA_SCTP_DAT_BUFSIZE;
	
	if ((dbuf = m2ua_recvmsg_lksctp(sg, fd, msg, dbuf, &m2ua_sctp_dat_len, cmsglen)) > 0)
	{
        /* Intercept notifications here */
        if (msg->msg_flags & MSG_NOTIFICATION)
            ret = m2ua_handle_event_lksctp(dbuf);
        else
        	ret = M2UA_LKSCTP_DATA_IND;
    }
    
	//outb(in_b & 0xFD, 0x378);
	
	return ret;
}

int expect_lksctp(int fd, int sg, int *msg, int want)
{
	int got;
	
	*msg = got = m2ua_sctp_get_msg_lksctp(fd, sg);
	
	if (got != -1)
	{
		if (((moniter_fg & MONITOR_SCTP) == MONITOR_SCTP) &&
			(m2ua_sg_mon_fg[sg] == 1))
		{
			if (m2ua_sctp_dat_len > 0)
			{
				sprintf(m2ua_ascitemp_buf, "Recv %s from SCTP, sg=%d, data len=%d\n\r", dec_sctp_primi_lksctp(got), sg, m2ua_sctp_dat_len);
				m2ua_asciout_proc(m2ua_ascitemp_buf);
				m2ua_hex_to_ascii(m2ua_sctp_dat, m2ua_sctp_dat_len, m2ua_ascitemp_buf);
				m2ua_asciout_proc(m2ua_ascitemp_buf);
				m2ua_asciout_proc("\n\r");
			}
		}
	}
	
	if (got == want)
		return M2UA_SUCCESS;
	else
		return M2UA_FAILURE;
}

int m2ua_sctp_discon_req_lksctp(int fd, int sg, int flag)
{
	BYTE	enable1, enable2, server;
	WORD lk;
	
	m2ua_sctp_close(fd, sg);
	if (sg < M2UA_MAX_SG_NUM)
	{
		//enable1	= m2ua_sg_info[sg].enable;	
		//m2ua_sg_init(sg);
		//m2ua_sg_info[sg].enable = enable1;
		m2ua_sg_info[sg].fd = 0;
	}
	
	if (((moniter_fg & MONITOR_SCTP) == MONITOR_SCTP) &&
		(m2ua_sg_mon_fg[sg] == 1))
	{
		sprintf(m2ua_ascitemp_buf, "m2ua_sctp_discon_req_lksctp succeed, sg=%d, fd=%d\n\r", sg, fd);
		m2ua_asciout_proc(m2ua_ascitemp_buf);
	}
	
	if ((flag == 0) || (sg >= M2UA_MAX_SG_NUM))
		return 0;
	
	enable1	= m2ua_sg_info[sg].enable;	
	enable2	= m2ua_para.sg_para[sg].enable;
	server	= m2ua_para.sg_para[sg].server;
	
	if (!server && enable1 && (enable2 == 1))
	{
		if ((fd = m2ua_sctp_open_lksctp(sg)) <= 0)
		{	
    	m2ua_sg_info[sg].enable = 0;
			for (lk = 0; lk < M2UA_MAX_LK_NUM; lk++)
			{
				if(m2ua_para.lk_para[lk].lk_sg == sg)
					m2ua_lk_info[lk].enable = 0;
			}
    	m2ua_log_err(sg, "M2UA lksctp open failure!");			
    }
		else
			m2ua_sg_info[sg].fd = fd;
  }
    
	return 1;
}

int m2ua_sctp_put_msg_lksctp(int fd, int sg)
{
	//BYTE	err_text[128];
	//BYTE	in_b;
	BYTE	ppid;
	struct 	sctp_sndrcvinfo *sri;
    struct 	msghdr msg[1];
    struct 	cmsghdr *cmsg;
    struct 	iovec iov[1];
    int 	cmsglen = sizeof(*cmsg) + sizeof(*sri);
    int		ret;
	
	if (((moniter_fg & MONITOR_SCTP) == MONITOR_SCTP) &&
		(m2ua_sg_mon_fg[sg] == 1))
	{
		if (m2ua_sctp_dat_len > 0)
		{
			sprintf(m2ua_ascitemp_buf, "Send M2UA_LKSCTP_DATA to SCTP, sg=%d, data len=%d\n\r", sg, m2ua_sctp_dat_len);
			m2ua_asciout_proc(m2ua_ascitemp_buf);
			m2ua_hex_to_ascii(m2ua_sctp_dat, m2ua_sctp_dat_len, m2ua_ascitemp_buf);
			m2ua_asciout_proc(m2ua_ascitemp_buf);
			m2ua_asciout_proc("\n\r");
		}
	}
	
	//in_b = inb(0x378);
	//outb(in_b | 0x04, 0x378);
	//88 us
	
    /* Set up the msghdr structure for receiving */
    memset(msg, 0, sizeof (*msg));
    
    iov->iov_base = m2ua_sctp_data.buf;
   	iov->iov_len = m2ua_sctp_data.len;
   	msg->msg_iov = iov;
   	msg->msg_iovlen = 1;
   	
    msg->msg_control = m2ua_sctp_cmd.cbuf;
    msg->msg_controllen = cmsglen;
    msg->msg_flags = MSG_XPG4_2;
    
    cmsg = (struct cmsghdr *)m2ua_sctp_cmd.cbuf;
    sri = (struct sctp_sndrcvinfo *)(cmsg + 1);
    
    cmsg->cmsg_len = cmsglen;
    cmsg->cmsg_level = IPPROTO_SCTP;
    cmsg->cmsg_type = SCTP_SNDRCV;
    
    memset((BYTE *)sri, 0, sizeof(*sri));
   	sri->sinfo_stream = m2ua_sctp_data.sid;
   	//sri->sinfo_ppid = htonl(2); //m2ua
   	switch(m2ua_para.sg_para[sg].xUA_ack>>1)//SCTP Payload Protocol Identifier
   {
   		case M2UA_APP:
   			ppid = 2;
   			break;
   		case IUA_APP:	
   			ppid = 1;
   			break;
   		case M3UA_APP:	
   			ppid = 3;
   			break;
   		default:
   			ppid = 2;
   			break;   				
   }	
   	sri->sinfo_ppid = htonl(ppid);   	
    
    if ((ret = sendmsg(fd, msg, MSG_NOSIGNAL)) < 0)
    {
    		BYTE	ascitemp_buf[256];
        sprintf(ascitemp_buf, "ret=%d,lksctp sendmsg failure: %d(%s)", ret,errno, strerror(errno));
        m2ua_log_err(sg, ascitemp_buf);
        return -1;
    }
   	
   	//outb(in_b & 0xFB, 0x378);
   	
   	return 0;
}

int m2ua_sctp_optdata_req_lksctp(int fd, int sg, int len)
{
	if (!len)
		return (-1);
	else
	{
		if (len > M2UA_MAX_MSG_LEN)
			return (-1);
		else
			m2ua_sctp_data.len = len;
	}
	
	return m2ua_sctp_put_msg_lksctp(fd, sg);
}

#endif
