#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; }