#include "./include/radius_pub.h"

int radius_set_nas_info(BYTE sap_index, BYTE id, RADIUS_NAS_INFORMATION *nas_information)
{
	RADIUS_NAS_INFO	*nas_info_ptr;

	if ((sap_index >= RADIUS_MAX_NUM_OF_SAP) || ((nas_info_ptr = radius_get_nas_info_ptr(id)) == NULL))
	{
		radius_log_err("%s: sap_index=%d, nas id=%d\r\n", __FUNCTION__, sap_index, id);
		return -1;
	}

	nas_info_ptr->flag = 1;

	nas_info_ptr->sap_index = sap_index;

	nas_info_ptr->nas_ip = nas_information->nas_ip;
	strcpy((char*)nas_info_ptr->share_key, (char*)nas_information->share_key);
	strcpy((char*)nas_info_ptr->password, (char*)nas_information->password);

	return 0;
}

int radius_delet_nas_info(BYTE sap_index, BYTE id)
{
	RADIUS_NAS_INFO	*nas_info_pt;

	if (((nas_info_pt = radius_get_nas_info_ptr(id)) == NULL) || (nas_info_pt->flag != 1) || (nas_info_pt->sap_index != sap_index))
	{
		radius_log_err("%s: sap_index=%d, nas id=%d\r\n", __FUNCTION__, sap_index, id);
		return -1;
	}

	memset(nas_info_pt, 0, sizeof(RADIUS_NAS_INFO));

	return 0;
}
/*
int radius_set_local_nas(BYTE sap_index, char *nas_password, char *nas_share_key)
{
	if (sap_index >= RADIUS_MAX_NUM_OF_SAP)
	{
		radius_log_err("%s: sap_index=%d\r\n", __FUNCTION__, sap_index);
		return -1;
	}

	strcpy(radius_nas_password[sap_index], nas_password);
	strcpy(radius_nas_share_key[sap_index], nas_share_key);

	return 0;
}*/

int radius_send_access_request(BYTE sap_index, WORD usr_pid, RADIUS_MSG *msg_pdu, RADIUS_ADDR *addr)
{
	int			pid;
	BYTE		identifier;
	BYTE		authenticator[RADIUS_MAX_LEN_OF_AUTH];
	int			msg_len, nas_id;
	BYTE		msg[RADIUS_MAX_LEN_OF_MSG] = "";
	RADIUS_PID	*pid_ptr;
	struct in_addr		ip_addr;
//	int			server_id;
//	struct in_addr		ip_addr;

	if ((sap_index >= RADIUS_MAX_NUM_OF_SAP) || (msg_pdu == NULL) || (addr == NULL))
	{
		radius_log_err("%s: sap_index=%d, msg_pdu=0x%X, addr=ox%X\r\n", __FUNCTION__, sap_index, msg_pdu, addr);
		return -1;
	}
	radius_log_event("%s: enter! usr_pid=%d\r\n", __FUNCTION__, usr_pid);

/*	if ((server_id = radius_accord_ip_search_server_info(addr->addr.ipV4)) < 0)
	{
		ip_addr.s_addr = addr->addr.ipV4;
		radius_log_err("%s: server ip=%s, no such nas\r\n", __FUNCTION__, inet_ntoa(ip_addr));
		return -1;
	}*/
	if ((nas_id = radius_accord_ip_search_nas_info(addr->addr.ipV4)) < 0)
	{
		ip_addr.s_addr = addr->addr.ipV4;
		radius_log_warn("%s: nas ip = %s, no such nas ip\r\n", __FUNCTION__, inet_ntoa(ip_addr));
		return -1;
	}

	if ((msg_len = radius_encode_access_request(sap_index, &identifier, authenticator, msg, &msg_pdu->msg.access_request, nas_id)) < 0)
	{
		radius_log_err("%s: encode access request fail\r\n", __FUNCTION__);
		return -1;
	}

	if ((pid = radius_get_pid()) < 0)
	{
		radius_log_err("%s: get pid fail\r\n", __FUNCTION__);
		return -1;
	}

	pid_ptr = radius_get_pid_ptr(pid);

	pid_ptr->type = RADIUS_PID_TYPE_REQ;

	pid_ptr->identifier = identifier;
	memcpy(pid_ptr->authenticator, authenticator, RADIUS_MAX_LEN_OF_AUTH);

	pid_ptr->sd_msg_flag = 1;
	pid_ptr->sd_msg_type = RADIUS_MSG_TYPE_ACCESS_REQUEST;

	memcpy(&pid_ptr->peer_addr, addr, sizeof(RADIUS_ADDR));
	pid_ptr->peer_addr.port = RADIUS_ACCESS_PORT;

	memcpy(pid_ptr->msg, msg, msg_len);
	pid_ptr->msg_len = msg_len;

	pid_ptr->timer = RADIUS_TIMER_16S;

	pid_ptr->sap_index = sap_index;
	pid_ptr->usr_pid = usr_pid;

	radius_log_event("%s: success! usr_pid=%d, pid=%d\r\n", __FUNCTION__, usr_pid, pid);
//	radius_p_fsm(pid);

	return pid;
}

int radius_send_access_accept(BYTE sap_index, WORD pid, WORD usr_pid, RADIUS_MSG *msg_pdu)
{
	int			msg_len;
	BYTE		msg[RADIUS_MAX_LEN_OF_MSG] = "";
	RADIUS_PID	*pid_ptr;

	if ((sap_index >= RADIUS_MAX_NUM_OF_SAP) || (msg_pdu == NULL)
		|| ((pid_ptr = radius_get_pid_ptr(pid)) == NULL) || (pid_ptr->sap_index != sap_index) 
		|| (pid_ptr->usr_pid != usr_pid)
		|| (pid_ptr->trans_req_msg_type != RADIUS_MSG_TYPE_ACCESS_REQUEST))
	{
		radius_log_err("%s: sap_index=%d, msg_pdu=0x%X, pid=%d, usr_pid=%d\r\n", __FUNCTION__, sap_index, msg_pdu, pid, usr_pid);
		return -1;
	}

	if ((msg_len = radius_encode_access_accept(pid_ptr->identifier, pid_ptr->authenticator, msg, &msg_pdu->msg.access_accept, pid_ptr->nas_id)) < 0)
	{
		radius_log_err("%s: encode access accept fail\r\n", __FUNCTION__);
		return -1;
	}

	pid_ptr->sd_msg_flag = 1;
	pid_ptr->sd_msg_type = RADIUS_MSG_TYPE_ACCESS_ACCEPT;

	memcpy(pid_ptr->msg, msg, msg_len);
	pid_ptr->msg_len = msg_len;
	radius_log_event("%s: success! usr_pid=%d, pid=%d\r\n", __FUNCTION__, usr_pid, pid);

	return 0;
}

int radius_send_access_reject(BYTE sap_index, WORD pid, WORD usr_pid, RADIUS_MSG *msg_pdu)
{
	int			msg_len;
	BYTE		msg[RADIUS_MAX_LEN_OF_MSG] = "";
	RADIUS_PID	*pid_ptr;

	if ((sap_index >= RADIUS_MAX_NUM_OF_SAP) || (msg_pdu == NULL)
		|| ((pid_ptr = radius_get_pid_ptr(pid)) == NULL) || (pid_ptr->sap_index != sap_index)
		|| (pid_ptr->usr_pid != usr_pid)
		|| (pid_ptr->trans_req_msg_type != RADIUS_MSG_TYPE_ACCESS_REQUEST))
	{
		radius_log_err("%s: sap_index=%d, msg_pdu=0x%X, pid=%d, usr_pid=%d\r\n", __FUNCTION__, sap_index, msg_pdu, pid, usr_pid);
		return -1;
	}

	if ((msg_len = radius_encode_access_reject(pid_ptr->identifier, pid_ptr->authenticator, msg, &msg_pdu->msg.access_reject, pid_ptr->nas_id)) < 0)
	{
		radius_log_err("%s: encode access reject fail\r\n", __FUNCTION__);
		return -1;
	}

	pid_ptr->sd_msg_flag = 1;
	pid_ptr->sd_msg_type = RADIUS_MSG_TYPE_ACCESS_REJECT;

	memcpy(pid_ptr->msg, msg, msg_len);
	pid_ptr->msg_len = msg_len;
	radius_log_event("%s: success! usr_pid=%d, pid=%d\r\n", __FUNCTION__, usr_pid, pid);

	return 0;
}

int radius_send_accounting_response(BYTE sap_index, WORD pid, WORD usr_pid, RADIUS_MSG *msg_pdu)
{
	int			msg_len;
	BYTE		msg[RADIUS_MAX_LEN_OF_MSG] = "";
	RADIUS_PID	*pid_ptr;

	if ((sap_index >= RADIUS_MAX_NUM_OF_SAP) || (msg_pdu == NULL)
		|| ((pid_ptr = radius_get_pid_ptr(pid)) == NULL) || (pid_ptr->sap_index != sap_index) || (pid_ptr->usr_pid != usr_pid) || (pid_ptr->trans_req_msg_type != RADIUS_MSG_TYPE_ACCOUNTING_REQUEST))
	{
		radius_log_err("%s: sap_index=%d, msg_pdu=0x%X, pid=%d, usr_pid=%d\r\n", __FUNCTION__, sap_index, msg_pdu, pid, usr_pid);
		return -1;
	}

	if ((msg_len = radius_encode_accounting_response(pid_ptr->identifier, pid_ptr->authenticator, msg, &msg_pdu->msg.accounting_response, pid_ptr->nas_id)) < 0)
	{
		radius_log_err("%s: encode accounting response fail\r\n", __FUNCTION__);
		return -1;
	}

	pid_ptr->sd_msg_flag = 1;
	pid_ptr->sd_msg_type = RADIUS_MSG_TYPE_ACCOUNTING_RESPONSE;

	memcpy(pid_ptr->msg, msg, msg_len);
	pid_ptr->msg_len = msg_len;
	radius_log_event("%s: success! usr_pid=%d, pid=%d\r\n", __FUNCTION__, usr_pid, pid);

	return 0;
}

int radius_send_disconnect_request(BYTE sap_index, WORD usr_pid, RADIUS_MSG *msg_pdu, RADIUS_ADDR *addr)
{
	int			pid;
	BYTE		identifier;
	BYTE		authenticator[RADIUS_MAX_LEN_OF_AUTH];
	int			msg_len;
	BYTE		msg[RADIUS_MAX_LEN_OF_MSG] = "";
	RADIUS_PID	*pid_ptr;
	int			nas_id;
	struct in_addr		ip_addr;

	if ((sap_index >= RADIUS_MAX_NUM_OF_SAP) || (msg_pdu == NULL) || (addr == NULL))
	{
		radius_log_err("%s: sap_index=%d, msg_pdu=0x%X, addr=ox%X\r\n", __FUNCTION__, sap_index, msg_pdu, addr);
		return -1;
	}

	if ((nas_id = radius_accord_ip_search_nas_info(addr->addr.ipV4)) < 0)
	{
		ip_addr.s_addr = addr->addr.ipV4;
		radius_log_err("%s: nas ip=%s, no such nas\r\n", __FUNCTION__, inet_ntoa(ip_addr));
		return -1;
	}

	if ((msg_len = radius_encode_disconnect_request(&identifier, authenticator, msg, &msg_pdu->msg.disconnect_request, nas_id)) < 0)
	{
		radius_log_err("%s: encode disconnect request fail\r\n", __FUNCTION__);
		return -1;
	}

	if ((pid = radius_get_pid()) < 0)
	{
		radius_log_err("%s: get pid fail\r\n", __FUNCTION__);
		return -1;
	}

	pid_ptr = radius_get_pid_ptr(pid);

	pid_ptr->type = RADIUS_PID_TYPE_REQ;

	pid_ptr->identifier = identifier;
	memcpy(pid_ptr->authenticator, authenticator, RADIUS_MAX_LEN_OF_AUTH);

	pid_ptr->sd_msg_flag = 1;
	pid_ptr->sd_msg_type = RADIUS_MSG_TYPE_DISCONNECT_REQUEST;

	memcpy(&pid_ptr->peer_addr, addr, sizeof(RADIUS_ADDR));
	pid_ptr->peer_addr.port = RADIUS_DISCONNECT_PORT;

	memcpy(pid_ptr->msg, msg, msg_len);
	pid_ptr->msg_len = msg_len;

	pid_ptr->timer = RADIUS_TIMER_16S;

	pid_ptr->sap_index = sap_index;
	pid_ptr->nas_id = nas_id;
	radius_log_event("%s: success! usr_pid=%d, pid=%d\r\n", __FUNCTION__, usr_pid, pid);

//	radius_p_fsm(pid);

	return pid;
}

