Files
ocs/plat/radius/src/radius_fsm.c
2025-03-03 11:01:26 +08:00

341 lines
7.4 KiB
C

#include "./include/radius_pub.h"
#define test_nowsms_enable 0
#define test_css_enable 0
#define radius_set_pid_state(val) do { \
pid_ptr->state = val; \
radius_log_event("[%05d] \33[32m%s\33[0m transfer to state \33[36m%s\33[0m\r\n", pid, __FUNCTION__, #val); \
} while(0)
#define radius_set_pid_timer(val) do { \
pid_ptr->timer = val; \
} while(0)
#if(test_nowsms_enable)
static void radius_test(int pid, BYTE sap_index, WORD *usr_pid, RADIUS_MSG *ptr_radius)
{
RADIUS_MSG pdu;
if(usr_pid == NULL || ptr_radius == NULL)
return;
memset(&pdu, 0, sizeof(RADIUS_MSG));
pdu.msg_type = RADIUS_MSG_TYPE_ACCESS_ACCEPT;
pdu.msg.access_accept.message_authenticator.flag = 1;
radius_send_access_accept(sap_index, pid, *usr_pid, &pdu);
return;
}
#elif(test_css_enable)
static void radius_test(int pid, BYTE sap_index, WORD *usr_pid, RADIUS_MSG *ptr_radius)
{
static BYTE user_id = 0;
BYTE count = 0;
int num, i;
RADIUS_MSG pdu;
RADIUS_ACCESS_ACCEPT *access_accept;
RADIUS_VENDOR_SPECIFIC *vendor_specific;
RADIUS_VENDOR_ATTRIBUTE_3GPP2_PPAC *ppac;
RADIUS_VENDOR_ATTRIBUTE_3GPP2_PPAQ *ppaq;
if(usr_pid == NULL || ptr_radius == NULL)
return;
if(ptr_radius->msg.access_request.user_password.flag == 1)
{
count = 1;
*usr_pid = user_id;
user_id++;
}
else if((num = ptr_radius->msg.access_request.vendor_specific.num) > 0)
{
for(i = 0; i < num; i++)
{
vendor_specific = &ptr_radius->msg.access_request.vendor_specific;
ppaq = &vendor_specific->vendor_specific[i].attribute_3gpp2.ppaq;
if((vendor_specific->vendor_specific[i].vendor_type == RADIUS_VENDOR_TYPE_3GPP2_PPAQ) && (ppaq->qid.flag == 1))
{
*usr_pid = (ppaq->qid.qid.value >> 16) & 0xFF;
count = (ppaq->qid.qid.value & 0xFF) + 1;
}
}
}
memset(&pdu, 0, sizeof(RADIUS_MSG));
pdu.msg_type = RADIUS_MSG_TYPE_ACCESS_ACCEPT;
access_accept = &pdu.msg.access_accept;
vendor_specific = &access_accept->vendor_specific;
num = vendor_specific->num;
vendor_specific->vendor_specific[num].flag = 1;
vendor_specific->vendor_specific[num].vendor_type = RADIUS_VENDOR_TYPE_3GPP2_PPAC;
ppac = &vendor_specific->vendor_specific[num].attribute_3gpp2.ppac;
ppac->sfs.flag = 1;
//ppac->sfs.sfs = 2; //dt && dq
ppac->sfs.sfs = 1; //vt && vq
vendor_specific->num++;
num = vendor_specific->num;
vendor_specific->vendor_specific[num].vendor_type = RADIUS_VENDOR_TYPE_3GPP2_PPAQ;
ppaq = &vendor_specific->vendor_specific[num].attribute_3gpp2.ppaq;
ppaq->qid.flag = 1;
ppaq->qid.qid.value = ((*usr_pid) << 16) | (count * 1);
if(ppac->sfs.sfs == 1)
{
ppaq->vq.flag = 1;
ppaq->vq.vq.integer = (count + 1) * 1024 * 20;
ppaq->vq.vq.exponent = 1;
ppaq->vt.flag = 1;
ppaq->vt.vt.integer = (count + 1) * 1024 * 20 - 1024 * 2;
ppaq->vt.vt.exponent = 1;
}
else if(ppac->sfs.sfs == 2)
{
ppaq->dq.flag = 1;
ppaq->dq.dq.value = count * 20;
ppaq->dt.flag = 1;
ppaq->dt.dt.value = count * 20 - 2;
}
vendor_specific->num++;
access_accept->message_authenticator.flag = 1;
radius_send_access_accept(sap_index, pid, *usr_pid, &pdu);
return;
}
#endif
int radius_pid_indication_process(int pid)
{
BYTE sap_index;
RADIUS_PID *pid_ptr;
pid_ptr = radius_get_pid_ptr(pid);
sap_index = pid_ptr->sap_index;
switch (pid_ptr->state)
{
case RADIUS_PID_IND_STATE_IDLE:
if (pid_ptr->rv_msg_flag != 0)
{
pid_ptr->rv_msg_flag = 0;
if (radius_sap[sap_index].radius_ind == NULL)
return 1;
#if(test_nowsms_enable || test_css_enable)
{
radius_test(pid, sap_index, &pid_ptr->usr_pid, &radius_msg_pdu);
}
#else
if (radius_sap[sap_index].radius_ind(&pid_ptr->usr_pid, pid, &radius_msg_pdu) < 0)
{
radius_log_err("[%04d] %s: radius_ind error! usr_pid=%d\r\n", pid, __FUNCTION__, pid_ptr->usr_pid);
return 1;
}
#endif
radius_log_event("[%04d] %s: recv indication and send it to up layer\r\n", pid, __FUNCTION__);
radius_set_pid_state(RADIUS_PID_IND_STATE_WAIT_FOR_USER_RESP);
radius_set_pid_timer(RADIUS_TIMER_16S);
}
else
{
return 1;
}
break;
case RADIUS_PID_IND_STATE_WAIT_FOR_USER_RESP:
if (pid_ptr->sd_msg_flag == 1)
{
pid_ptr->sd_msg_flag = 0;
radius_send_msg(pid);
radius_set_pid_timer(RADIUS_TIMER_16S);
radius_set_pid_state(RADIUS_PID_IND_STATE_WAIT_FOR_TERMINATE);
break;
}
if (pid_ptr->timer > 0)
{
if (--pid_ptr->timer == 0)
{
radius_log_warn("[%04d] %s: wait user response time out\r\n", pid, __FUNCTION__);
radius_set_pid_state(RADIUS_PID_IND_STATE_TERMINATE);
return 1;
}
}
break;
case RADIUS_PID_IND_STATE_WAIT_FOR_TERMINATE:
if (pid_ptr->rv_msg_flag != 0)
{
radius_send_msg(pid);
pid_ptr->rv_msg_flag = 0;
}
if (pid_ptr->timer > 0)
{
if (--pid_ptr->timer == 0)
{
radius_set_pid_state(RADIUS_PID_IND_STATE_TERMINATE);
return 1;
}
}
break;
}
return 0;
}
int radius_pid_indication_fsm(int pid)
{
switch (radius_pid_indication_process(pid))
{
case 0:
break;
case 1:
radius_init_pid(pid);
break;
}
return 0;
}
int radius_pid_request_process(int pid)
{
BYTE sap_index;
RADIUS_PID *pid_ptr;
pid_ptr = radius_get_pid_ptr(pid);
sap_index = pid_ptr->sap_index;
switch (pid_ptr->state)
{
case RADIUS_PID_REQ_STATE_IDLE:
if (pid_ptr->sd_msg_flag == 1)
{
pid_ptr->sd_msg_flag = 0;
radius_send_msg(pid);
radius_set_pid_state(RADIUS_PID_REQ_STATE_WAIT_FOR_PEER_RESP);
radius_set_pid_timer(RADIUS_TIMER_16S);
break;
}
if (pid_ptr->timer > 0)
{
if (--pid_ptr->timer == 0)
{
return 1;
}
}
else
{
return 1;
}
break;
case RADIUS_PID_REQ_STATE_WAIT_FOR_PEER_RESP:
if (pid_ptr->rv_msg_flag != 0)
{
radius_log_event("[%04d]%s: recv peer response and send it to up layer\r\n", pid, __FUNCTION__);
radius_set_pid_state(RADIUS_PID_REQ_STATE_TERMINATE);
if (radius_sap[sap_index].radius_cnf == NULL)
{
radius_log_err("[%04d] %s: radius_cnf error! usr_pid=%d\r\n", pid, __FUNCTION__, pid_ptr->usr_pid);
return 1;
}
radius_sap[sap_index].radius_cnf(pid_ptr->usr_pid, pid, &radius_msg_pdu);
return 1;
}
if (pid_ptr->timer > 0)
{
if (--pid_ptr->timer == 0)
{
radius_log_warn("[%04d] %s: wait peer response time out\r\n", pid, __FUNCTION__);
radius_set_pid_state(RADIUS_PID_REQ_STATE_TERMINATE);
return 1;
}
else
{
if ((pid_ptr->timer % RADIUS_RETRANS_TIMER) == 0)
{
radius_send_msg(pid);
}
}
}
break;
default:
return 1;
}
return 0;
}
int radius_pid_request_fsm(int pid)
{
switch (radius_pid_request_process(pid))
{
case 0:
break;
case 1:
radius_init_pid(pid);
break;
}
return 0;
}
int radius_p_fsm(int pid)
{
RADIUS_PID *pid_ptr;
if ((pid_ptr = radius_get_pid_ptr(pid)) == NULL)
return -1;
switch (pid_ptr->type)
{
case RADIUS_PID_TYPE_IND:
radius_pid_indication_fsm(pid);
break;
case RADIUS_PID_TYPE_REQ:
radius_pid_request_fsm(pid);
break;
default:
radius_init_pid(pid);
break;
}
return 0;
}
int radius_fsm(void)
{
int i;
RADIUS_PID *pid_ptr;
for (i = 0; i < RADIUS_MAX_NUM_OF_PID; i++)
{
pid_ptr = radius_get_pid_ptr(i);
if (pid_ptr->flag != 1)
continue;
radius_p_fsm(i);
}
return 0;
}