📄 radius_tx.c
字号:
{ /* allocate new packet identifier */ if (radius_get_next_available_packet_identifier_per_server (p_server, &p_server->packet_identifier_count) == FAIL) { /* skip this one, wait for the next timer */ *ep_error_packet_id = false; radius_printf (RADIUS_ALARM_PRINTF,"RADIUS Retransmission: Failed to get next available packet identifier.\r\n"); return; } /* initialize this packet id's reused timer before freeing it to avoid using it right away. If the response for this packet id arrived, we could be mistaken for the new request */ radius_set_packet_id_reused_timer_before_reuse_per_server (p_server, sptr_packet->header.identifier); /* update packet identifier in local structures */ sptr_packet->header.identifier = (BYTE) (p_server->packet_identifier_count); sptr_request_entry->packet_header.identifier = (BYTE) (p_server->packet_identifier_count); /* Update attribute in the packet */ bp_value = &sptr_attribute_entry_in_packet->value[0]; delay_time = deserialize_ulong (&bp_value); delay_time += retransmission_interval; bp_value = &sptr_attribute_entry_in_packet->value[0]; serialize_ulong (delay_time, &bp_value); /* encrpt the modified packet */ memset (&sptr_packet->header.authenticator[0], 0, RADIUS_SIZE_OF_AUTHENTICATOR); if (radius_accounting_fill_in_request_authenticator (sptr_packet, total_packet_length, p_server, (BYTE *)&sptr_packet->header.authenticator[0]) == false) { /* skip this one, wait for the next timer */ *ep_error_packet_id = false; radius_printf (RADIUS_ALARM_PRINTF,"RADIUS Retransmission: radius_accounting_fill_in_request_authenticator() failed\n"); return; } radius_printf (RADIUS_DATA_PRINTF,"RADIUS Retransmission: Updated Delay_time to %d and ID to %d.\r\n", delay_time, sptr_packet->header.identifier); return; } attribute_length = (UINT) sptr_attribute_entry_in_packet->length; packet_length -= attribute_length; sptr_attribute_entry_in_packet = (RADIUS_ATTRIBUTE_ENTRY_IN_PACKET *) ((UINT) sptr_attribute_entry_in_packet + attribute_length); } return;}/******************************************************************************************Function: resend_radius_packetDescription: Resend the RADIUS request packet after the retransmission interval expires. However, if the max_retransmit_count has been exceeded, it will search for the next available server of the right type (authentication or accounting). If the search is found, it resends the packet to the new server. Otherwise, it sends an error message back to the requester.******************************************************************************************/enum TEST resend_radius_packet (RADIUS_REQUEST_ENTRY *sptr_request_entry){ RADIUS_PACKET *sptr_packet; RADIUS_SERVER *p_server, *p_server_tmp; RW_CONTAINER_ITERATOR server_iterator, server_iterator_tmp; bool packet_id_availability, next_server_available = false; struct in_addr inetAddr; BYTE ip_string[18]; ULONG value; /* These 2 lines are just to get rid of compiler warnings */ p_server_tmp = NULL; server_iterator_tmp = (RW_CONTAINER_ITERATOR)NULL; packet_id_availability = true; if (sptr_request_entry->backup_server == true) { server_iterator = (RW_CONTAINER_ITERATOR) sptr_request_entry->backup_server_handle; } else { server_iterator = (RW_CONTAINER_ITERATOR) sptr_request_entry->server_handle; } p_server = (RADIUS_SERVER*) rw_container_at (server_iterator); sptr_packet = sptr_request_entry->sptr_packet; ++sptr_request_entry->request_retry_count; if (sptr_request_entry->request_retry_count > p_server->max_retransmit_count) { radius_printf(RADIUS_TRACE_PRINTF, "Retry count expires\n"); /* set reused timer just incase we don't use this packet id right away which might cause corrupted response */ radius_set_packet_id_reused_timer_before_reuse_per_server (p_server, sptr_packet->header.identifier); /* check if another RADIUS server is available */ if (sptr_request_entry->any_server == true && (sptr_request_entry->backup_server_handle = radius_get_next_server(server_iterator, p_server->type)) != INVALID_HANDLE) { /* yes, another RADIUS server is available */ /* update the info in current RADIUS_REQUEST_ENTRY structure */ radius_printf(RADIUS_TRACE_PRINTF, "Found a back-up server, server handle = 0x%x\n", sptr_request_entry->backup_server_handle); sptr_request_entry->request_time = 0; sptr_request_entry->request_retry_count = 0; /* the rest of the info should stay the same, now save this RADIUS server temporarily */ server_iterator_tmp = (RW_CONTAINER_ITERATOR) sptr_request_entry->backup_server_handle; p_server_tmp = (RADIUS_SERVER*) rw_container_at (server_iterator_tmp); next_server_available = true; /* update pending request and statistics for the back-up server */ ++p_server_tmp->pending_request_count;#ifdef __RADIUS_MIB__ semTake (g_sem_radius_mib, WAIT_FOREVER);#endif switch (sptr_request_entry->packet_header.code) { case RADIUS_ACCESS_REQUEST: ++p_server_tmp->statistics.authentication_access_requests_tx; ++p_server_tmp->statistics.authentication_pending_access_requests; break; case RADIUS_ACCOUNTING_REQUEST: ++p_server_tmp->statistics.accounting_requests_tx; ++p_server_tmp->statistics.accounting_pending_access_requests; break; default: /* should not happen! */ break; }#ifdef __RADIUS_MIB__ semGive (g_sem_radius_mib);#endif /* decrement pending request count on current server as the request is now handled by another server */ --p_server->pending_request_count; } else /* there is no more RADIUS server available, send error msg to requester */ { radius_printf(RADIUS_TRACE_PRINTF, "No more server available\n"); rwos_mutex_release (rwos_radius_data_mutex); (*sptr_request_entry->p_callbacks->fptr_radius_error_callback) (sptr_request_entry->request_handle, RADIUS_RETRY_LIMIT_REACHED); rwos_mutex_acquire (rwos_radius_data_mutex, WAIT_FOREVER); --p_server->pending_request_count; radius_printf(RADIUS_TRACE_PRINTF, "Pending request count = %d\n", p_server->pending_request_count); next_server_available = false; } /* tk: check if there has been a call to destroy the server. Delete the server only if there is no pending request on the server and there is no pending client who still owns (i.e. has not freed) all the copies of the server handle. */ if ((p_server->deleted == true) && (p_server->pending_request_count == 0) && (p_server->user_count == 0)) { radius_printf(RADIUS_TRACE_PRINTF, "Resend done: Server deleted\n"); rw_container_remove (server_iterator); if (p_server->bp_secret != NULL) { table_free (p_server->bp_secret); } table_free (p_server); } /* free copy of target server handle or the back-up server handle */ rw_container_free_iterator (server_iterator);#ifdef __RADIUS_MIB__ semTake (g_sem_radius_mib, WAIT_FOREVER);#endif switch (sptr_request_entry->packet_header.code) { case RADIUS_ACCESS_REQUEST: --p_server->statistics.authentication_pending_access_requests; break; case RADIUS_ACCOUNTING_REQUEST: --p_server->statistics.accounting_pending_access_requests; break; default: /* should not happen! */ break; }#ifdef __RADIUS_MIB__ semGive (g_sem_radius_mib);#endif if (next_server_available == true) { p_server = p_server_tmp; /* set p_server to the new Radius server */ server_iterator = server_iterator_tmp; sptr_request_entry->backup_server = true; /* display IP address of next server */ radius_util_serialize_ulong(p_server->ip_address, (BYTE *)&value); inetAddr.s_addr = value; inet_ntoa_b(inetAddr, ip_string); radius_printf(RADIUS_DATA_PRINTF, "Sending to another server %s\n", ip_string); } else { return (FAIL); } } if (sptr_request_entry->packet_header.code == RADIUS_ACCOUNTING_REQUEST) { update_delay_time_for_retransmission (sptr_packet, sptr_request_entry, p_server->retransmission_interval, p_server, &packet_id_availability); if (packet_id_availability == false) { return (PASS); /* wait for the next timer */ } } sptr_request_entry->request_timestamp = rwos_get_system_elapsed_time (); radius_printf(RADIUS_TRACE_PRINTF, "Resending request ...\n"); if (send_radius_udp_packet (sptr_packet, sptr_request_entry->packet_header.code, sptr_request_entry->packet_header.length, p_server) == FAIL) { /* free packet id right away and need not wait for reused timer because we are unable to send */ radius_free_packet_identifier_per_server (p_server, sptr_request_entry->packet_header.identifier); rwos_mutex_release (rwos_radius_data_mutex); (*sptr_request_entry->p_callbacks->fptr_radius_error_callback) (sptr_request_entry->request_handle, RADIUS_UDP_SEND_ERROR); rwos_mutex_acquire (rwos_radius_data_mutex, WAIT_FOREVER); --p_server->pending_request_count;#ifdef __RADIUS_MIB__ semTake (g_sem_radius_mib, WAIT_FOREVER);#endif switch (sptr_request_entry->packet_header.code) { case RADIUS_ACCESS_REQUEST: --p_server->statistics.authentication_pending_access_requests; break; case RADIUS_ACCOUNTING_REQUEST: --p_server->statistics.accounting_pending_access_requests; break; default: /* should not happen! */ break; }#ifdef __RADIUS_MIB__ semGive (g_sem_radius_mib);#endif /* tk: check if there has been a call to destroy the server. Delete the server only if there is no pending request on the server and there is no pending client who still owns (i.e. has not freed) all the copies of the server handle. */ if ((p_server->deleted == true) && (p_server->pending_request_count == 0) && (p_server->user_count == 0)) { radius_printf(RADIUS_TRACE_PRINTF, "Resend failed: Server deleted\n"); if (p_server->bp_secret != NULL) { table_free (p_server->bp_secret); } table_free (p_server); rw_container_remove (server_iterator); /* free the p_node */ } /* free copy of target server handle or the back-up server handle */ rw_container_free_iterator (server_iterator); return (FAIL); }#ifdef __RADIUS_MIB__ semTake (g_sem_radius_mib, WAIT_FOREVER);#endif switch (sptr_request_entry->packet_header.code) { case RADIUS_ACCESS_REQUEST: ++p_server->statistics.authentication_access_requests_retransmit; break; case RADIUS_ACCOUNTING_REQUEST: ++p_server->statistics.accounting_requests_retransmit; break; default: /* should not happen! */ break; }#ifdef __RADIUS_MIB__ semGive (g_sem_radius_mib);#endif return (PASS);}/************************************************************************/static enum TEST send_radius_udp_packet (RADIUS_PACKET *sptr_packet, enum RADIUS_CODE code, UINT length, RADIUS_SERVER* p_server){ struct sockaddr_in remote_sockaddr_in; int socket_descriptor; print_radius_packet_header ("send_radius_udp_packet", &sptr_packet->header); switch (code) { case RADIUS_ACCESS_REQUEST: socket_descriptor = radius.authentication_socket_object.socket_descriptor; break; case RADIUS_ACCOUNTING_REQUEST: socket_descriptor = radius.accounting_socket_object.socket_descriptor; break; default: radius_printf (RADIUS_ALARM_PRINTF,"RADIUS: send_radius_udp_packet: Illegal packet type to send - %d\r\n", code); return (FAIL); } remote_sockaddr_in.sin_family = AF_INET; remote_sockaddr_in.sin_addr.s_addr = htonl (p_server->ip_address); remote_sockaddr_in.sin_port = htons ((USHORT) p_server->port); if ((socket_descriptor == 0) || (remote_sockaddr_in.sin_port == 0x0000) || (remote_sockaddr_in.sin_addr.s_addr == 0x00000000L)) { radius_printf (RADIUS_SOCKET_PRINTF, "RADIUS: send_radius_udp_packet: illegal parameter\n"); return (FAIL); }#ifdef VIRTUAL_STACK virtualStackNumTaskIdSet (0);#endif rwos_mutex_release (rwos_radius_data_mutex); if (sendto (socket_descriptor, (caddr_t) sptr_packet, (int) length, (int) NULL, (SOCKADDR *) &remote_sockaddr_in, sizeof (SOCKADDR)) == ERROR) { if (errnoGet() == OUT_OF_MBUF) { radius_printf (RADIUS_SOCKET_PRINTF, "RADIUS: Network buffer depleted.\n"); rwos_mutex_acquire (rwos_radius_data_mutex, WAIT_FOREVER); return (FAIL); } else { radius_printf (RADIUS_SOCKET_PRINTF, "RADIUS: send_radius_udp_packet: FAILED\n"); rwos_mutex_acquire (rwos_radius_data_mutex, WAIT_FOREVER); return (FAIL); } } rwos_mutex_acquire (rwos_radius_data_mutex, WAIT_FOREVER); return (PASS);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -