netx/addons/pppoe/nx_pppoe_server.c
2021-02-02 05:29:56 +00:00

4536 lines
243 KiB
C

/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** NetX Component */
/** */
/** PPP Over Ethernet (PPPoE) */
/** */
/**************************************************************************/
/**************************************************************************/
#define NX_PPPOE_SERVER_SOURCE_CODE
/* Force error checking to be disabled in this module */
#ifndef NX_DISABLE_ERROR_CHECKING
#define NX_DISABLE_ERROR_CHECKING
#endif
#ifndef TX_DISABLE_ERROR_CHECKING
#define TX_DISABLE_ERROR_CHECKING
#endif
/* Include necessary system files. */
#include "nx_api.h"
#include "nx_ip.h"
#include "nx_pppoe_server.h"
#include "nx_packet.h"
/* Define the PPPoE created list head pointer and count. */
NX_PPPOE_SERVER *_nx_pppoe_server_created_ptr = NX_NULL;
/* Define internal PPPoE services. */
static VOID _nx_pppoe_server_thread_entry(ULONG pppoe_server_ptr_value);
static VOID _nx_pppoe_server_packet_receive(NX_PPPOE_SERVER *pppoe_server_ptr, NX_PACKET *packet_ptr);
static VOID _nx_pppoe_server_discovery_packet_process(NX_PPPOE_SERVER *pppoe_server_ptr, NX_PACKET *packet_ptr, ULONG client_mac_msw, ULONG client_mac_lsw, UINT is_broadcast);
static VOID _nx_pppoe_server_session_packet_process(NX_PPPOE_SERVER *pppoe_server_ptr, NX_PACKET *packet_ptr, ULONG client_mac_msw, ULONG client_mac_lsw);
static UINT _nx_pppoe_server_discovery_send(NX_PPPOE_SERVER *pppoe_server_ptr, NX_PPPOE_CLIENT_SESSION *client_session_ptr, UINT code);
static VOID _nx_pppoe_server_packet_send(NX_PPPOE_SERVER *pppoe_server_ptr, NX_PPPOE_CLIENT_SESSION *client_session_ptr, NX_PACKET *packet_ptr, UINT command);
static UINT _nx_pppoe_server_tag_process(NX_PPPOE_SERVER *pppoe_server_ptr, NX_PPPOE_CLIENT_SESSION *client_session_ptr, UINT code, UCHAR *tag_ptr, ULONG length);
static ULONG _nx_pppoe_server_data_get(UCHAR *data, UINT size);
static VOID _nx_pppoe_server_data_add(UCHAR *data, UINT size, ULONG value);
static VOID _nx_pppoe_server_string_add(UCHAR *dest, UCHAR *source, UINT size);
static UINT _nx_pppoe_server_tag_string_add(UCHAR *data_ptr, UINT tag_type, UINT tag_length, UCHAR *tag_value_string, UINT *index);
static UINT _nx_pppoe_server_session_find(NX_PPPOE_SERVER *pppoe_server_ptr, ULONG client_mac_msw, ULONG client_mac_lsw,
ULONG session_id, UINT *session_index, NX_PPPOE_CLIENT_SESSION **client_session_ptr);
static UINT _nx_pppoe_server_session_cleanup(NX_PPPOE_CLIENT_SESSION *client_session_ptr);
#ifdef NX_PPPOE_SERVER_SESSION_CONTROL_ENABLE
static UCHAR *nx_pppoe_service_name[1];
#endif
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _nxe_pppoe_server_create PORTABLE C */
/* 6.1 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function checks for errors in the PPPoE Server instance create */
/* function call. */
/* */
/* INPUT */
/* */
/* pppoe_server_ptr Pointer to PPPoE control block*/
/* name Name of this PPPoE instance */
/* ip_ptr Pointer to IP control block */
/* interface_index IP Interface Index */
/* pppoe_link_driver User supplied link driver */
/* pool_ptr packet pool */
/* stack_ptr Pointer stack area for PPPoE */
/* stack_size Size of PPPoE stack area */
/* priority Priority of PPPoE thread */
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* _nx_pppoe_server_create Actual PPPoE instance create */
/* function */
/* */
/* CALLED BY */
/* */
/* Application */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
/* */
/**************************************************************************/
UINT _nxe_pppoe_server_create(NX_PPPOE_SERVER *pppoe_server_ptr, UCHAR *name, NX_IP *ip_ptr, UINT interface_index,
VOID (*pppoe_link_driver)(struct NX_IP_DRIVER_STRUCT *), NX_PACKET_POOL *pool_ptr,
VOID *stack_ptr, ULONG stack_size, UINT priority)
{
UINT status;
/* Check for invalid input pointers. */
if ((pppoe_server_ptr == NX_NULL) || (pppoe_server_ptr -> nx_pppoe_id == NX_PPPOE_SERVER_ID) ||
(ip_ptr == NX_NULL) || (ip_ptr -> nx_ip_id != NX_IP_ID) ||
(pppoe_link_driver == NX_NULL) || (pool_ptr == NX_NULL) ||
(pool_ptr -> nx_packet_pool_id != NX_PACKET_POOL_ID) ||
(stack_ptr == NX_NULL))
return(NX_PPPOE_SERVER_PTR_ERROR);
/* Check for invalid interface ID */
if(interface_index >= NX_MAX_PHYSICAL_INTERFACES)
return(NX_PPPOE_SERVER_INVALID_INTERFACE);
/* Check for interface being valid. */
if(!ip_ptr -> nx_ip_interface[interface_index].nx_interface_valid)
return(NX_PPPOE_SERVER_INVALID_INTERFACE);
/* Check for payload size of packet pool. */
if (pool_ptr -> nx_packet_pool_payload_size < NX_PPPOE_SERVER_MIN_PACKET_PAYLOAD_SIZE)
return(NX_PPPOE_SERVER_PACKET_PAYLOAD_ERROR);
/* Check for a memory size error. */
if (stack_size < TX_MINIMUM_STACK)
return(NX_PPPOE_SERVER_MEMORY_SIZE_ERROR);
/* Check the priority specified. */
if (priority >= TX_MAX_PRIORITIES)
return(NX_PPPOE_SERVER_PRIORITY_ERROR);
/* Call actual PPPoE server instance create function. */
status = _nx_pppoe_server_create(pppoe_server_ptr, name, ip_ptr, interface_index,
pppoe_link_driver, pool_ptr, stack_ptr, stack_size, priority);
/* Return completion status. */
return(status);
}
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _nx_pppoe_server_create PORTABLE C */
/* 6.1 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function creates an PPPoE Server instance, including setting */
/* up all appropriate data structures, creating PPPoE event flag */
/* object and PPPoE thread. */
/* */
/* INPUT */
/* */
/* pppoe_server_ptr Pointer to PPPoE control block*/
/* name Name of this PPPoE instance */
/* ip_ptr Pointer to IP control block */
/* interface_index Interface Index */
/* pppoe_link_driver User supplied link driver */
/* pool_ptr packet pool */
/* stack_ptr Pointer stack area for PPPoE */
/* stack_size Size of PPPoE stack area */
/* priority Priority of PPPoE thread */
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* tx_event_flags_create Create IP event flags */
/* tx_thread_create Create IP helper thread */
/* */
/* CALLED BY */
/* */
/* Application */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
/* */
/**************************************************************************/
UINT _nx_pppoe_server_create(NX_PPPOE_SERVER *pppoe_server_ptr, UCHAR *name, NX_IP *ip_ptr, UINT interface_index,
VOID (*pppoe_link_driver)(struct NX_IP_DRIVER_STRUCT *), NX_PACKET_POOL *pool_ptr,
VOID *stack_ptr, ULONG stack_size, UINT priority)
{
TX_INTERRUPT_SAVE_AREA
/* Initialize the PPPoE Server control block to zero. */
memset((void *) pppoe_server_ptr, 0, sizeof(NX_PPPOE_SERVER));
/* Save the PPPoE name. */
pppoe_server_ptr -> nx_pppoe_name = name;
/* Save the length of PPPoE name to avoid compute strlen repeatedly in _nx_pppoe_server_discovery_send. */
if (_nx_utility_string_length_check((char *)pppoe_server_ptr -> nx_pppoe_name,
&(pppoe_server_ptr -> nx_pppoe_name_length),
NX_MAX_STRING_LENGTH))
{
return(NX_PPPOE_SERVER_PTR_ERROR);
}
/* Save the IP pointer. */
pppoe_server_ptr -> nx_pppoe_ip_ptr = ip_ptr;
/* Setup the interface index and interface pointer. */
pppoe_server_ptr -> nx_pppoe_interface_ptr = &(ip_ptr -> nx_ip_interface[interface_index]);
/* Save the packet pool pointer. */
pppoe_server_ptr -> nx_pppoe_packet_pool_ptr = pool_ptr;
/* Setup the enabled flag. */
pppoe_server_ptr -> nx_pppoe_enabled = NX_FALSE;
/* Save the starting Session ID. */
pppoe_server_ptr -> nx_pppoe_session_id = NX_PPPOE_SERVER_START_SESSION_ID;
/* Initialize PPPoE notify function pointer */
pppoe_server_ptr -> nx_pppoe_discover_initiation_notify = NX_NULL;
pppoe_server_ptr -> nx_pppoe_discover_request_notify = NX_NULL;
pppoe_server_ptr -> nx_pppoe_discover_terminate_notify = NX_NULL;
pppoe_server_ptr -> nx_pppoe_discover_terminate_confirm = NX_NULL;
pppoe_server_ptr -> nx_pppoe_data_receive_notify = NX_NULL;
pppoe_server_ptr -> nx_pppoe_data_send_notify = NX_NULL;
/* Setup the link driver address. */
pppoe_server_ptr -> nx_pppoe_link_driver_entry = pppoe_link_driver;
/* Create event flag group to control the PPPoE processing thread. */
tx_event_flags_create(&(pppoe_server_ptr -> nx_pppoe_events), "PPPoE Server EVENTS") ;
/* Create the PPPoE processing thread. */
tx_thread_create(&(pppoe_server_ptr -> nx_pppoe_thread), "PPPoE Server THREAD", _nx_pppoe_server_thread_entry, (ULONG) pppoe_server_ptr,
stack_ptr, stack_size, priority, priority, NX_PPPOE_SERVER_THREAD_TIME_SLICE, TX_DONT_START);
/* Otherwise, the PPPoE initialization was successful. Place the
PPPoE control block on created PPPoE instance. */
TX_DISABLE
/* Load the PPPoE Server ID field in the PPPoE Server control block. */
pppoe_server_ptr -> nx_pppoe_id = NX_PPPOE_SERVER_ID;
/* Set the pointer of global variable PPPoE. */
_nx_pppoe_server_created_ptr = pppoe_server_ptr;
/* Restore previous interrupt posture. */
TX_RESTORE
/* Return success. */
return(NX_PPPOE_SERVER_SUCCESS);
}
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _nxe_pppoe_server_ac_name_set PORTABLE C */
/* 6.1 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function checks for errors in the PPPoE Server set Access */
/* Concentrator name function call. */
/* */
/* INPUT */
/* */
/* pppoe_server_ptr Pointer to PPPoE control block*/
/* ac_name Access Concentrator name */
/* ac_name_length Length of Name */
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* _nx_pppoe_server_ac_name_set Set Access Concentrator */
/* name function */
/* */
/* CALLED BY */
/* */
/* Application */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
/* */
/**************************************************************************/
UINT _nxe_pppoe_server_ac_name_set(NX_PPPOE_SERVER *pppoe_server_ptr, UCHAR *ac_name, UINT ac_name_length)
{
UINT status;
/* Check for invalid input pointers. */
if ((pppoe_server_ptr == NX_NULL) || (pppoe_server_ptr -> nx_pppoe_id != NX_PPPOE_SERVER_ID))
return(NX_PPPOE_SERVER_PTR_ERROR);
/* Call Access Concentrator name set function. */
status = _nx_pppoe_server_ac_name_set(pppoe_server_ptr, ac_name, ac_name_length);
/* Return completion status. */
return(status);
}
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _nx_pppoe_server_ac_name_set PORTABLE C */
/* 6.1 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function sets Access Concentrator name function call. */
/* */
/* Note: The string of ac_name must be NULL-terminated and length */
/* of ac_name matches the length specified in the argument list. */
/* */
/* INPUT */
/* */
/* pppoe_server_ptr Pointer to PPPoE control block*/
/* ac_name Access Concentrator name */
/* ac_name_length Length of Name */
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* _nx_utility_string_length_check Check string length */
/* */
/* CALLED BY */
/* */
/* Application */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
/* */
/**************************************************************************/
UINT _nx_pppoe_server_ac_name_set(NX_PPPOE_SERVER *pppoe_server_ptr, UCHAR *ac_name, UINT ac_name_length)
{
UINT temp_name_length = 0;
/* Get the length of ac_name string. */
if (_nx_utility_string_length_check((CHAR*)ac_name, &temp_name_length, ac_name_length))
return(NX_SIZE_ERROR);
/* Check the name length. */
if (ac_name_length != temp_name_length)
return(NX_SIZE_ERROR);
/* Obtain the IP internal mutex before processing the IP event. */
tx_mutex_get(&(pppoe_server_ptr -> nx_pppoe_ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
/* Save the nx_pppoe_ac_name. */
pppoe_server_ptr -> nx_pppoe_ac_name = ac_name;
/* Save the nx_pppoe_ac_name length. */
pppoe_server_ptr -> nx_pppoe_ac_name_length = ac_name_length;
/* Release the IP internal mutex. */
tx_mutex_put(&(pppoe_server_ptr -> nx_pppoe_ip_ptr -> nx_ip_protection));
/* Return success. */
return(NX_PPPOE_SERVER_SUCCESS);
}
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _nxe_pppoe_server_delete PORTABLE C */
/* 6.1 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function checks for errors in the PPPoE Server instance delete */
/* function call. */
/* */
/* INPUT */
/* */
/* pppoe_server_ptr Pointer to PPPoE control block*/
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* _nx_pppoe_server_delete Actual PPPoE instance delete */
/* function */
/* */
/* CALLED BY */
/* */
/* Application */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
/* */
/**************************************************************************/
UINT _nxe_pppoe_server_delete(NX_PPPOE_SERVER *pppoe_server_ptr)
{
UINT status;
/* Check for invalid input pointers. */
if ((pppoe_server_ptr == NX_NULL) || (pppoe_server_ptr -> nx_pppoe_id != NX_PPPOE_SERVER_ID))
return(NX_PPPOE_SERVER_PTR_ERROR);
/* Call actual PPPoE server instance delete function. */
status = _nx_pppoe_server_delete(pppoe_server_ptr);
/* Return completion status. */
return(status);
}
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _nx_pppoe_server_delete PORTABLE C */
/* 6.1 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function deletes an PPPoE Server instance. including deleting */
/* PPPoE event flag object and PPPoE thread. */
/* */
/* INPUT */
/* */
/* pppoe_server_ptr Pointer to PPPoE control block*/
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* tx_thread_terminate Terminate PPPoE helper thread */
/* tx_thread_delete Delete PPPoE helper thread */
/* tx_event_flags_delete Delete PPPoE event flags */
/* */
/* CALLED BY */
/* */
/* Application */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
/* */
/**************************************************************************/
UINT _nx_pppoe_server_delete(NX_PPPOE_SERVER *pppoe_server_ptr)
{
TX_INTERRUPT_SAVE_AREA
/* Determine if the caller is the PPPoE thread itself. This is not allowed since
a thread cannot delete itself in ThreadX. */
if (&pppoe_server_ptr -> nx_pppoe_thread == tx_thread_identify())
{
/* Invalid caller of this routine, return an error! */
return(NX_CALLER_ERROR);
}
/* Disable interrupts. */
TX_DISABLE
/* Clear the PPPOE ID to show that it is no longer valid. */
pppoe_server_ptr -> nx_pppoe_id = 0;
pppoe_server_ptr -> nx_pppoe_enabled = NX_FALSE;
/* Clear the created pointer. */
_nx_pppoe_server_created_ptr = NX_NULL;
/* Restore previous interrupt posture. */
TX_RESTORE
/* Terminate the thread. */
tx_thread_terminate(&(pppoe_server_ptr -> nx_pppoe_thread));
/* Delete the PPPoE thread. */
tx_thread_delete(&(pppoe_server_ptr -> nx_pppoe_thread));
/* Delete the event flag group. */
tx_event_flags_delete(&(pppoe_server_ptr -> nx_pppoe_events));
/* Return success. */
return(NX_PPPOE_SERVER_SUCCESS);
}
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _nxe_pppoe_server_enable PORTABLE C */
/* 6.1 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function checks for errors in the PPPoE Server enable function */
/* call. */
/* */
/* INPUT */
/* */
/* pppoe_server_ptr Pointer to PPPoE control block*/
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* _nx_pppoe_server_enable Actual PPPoE enable function */
/* */
/* CALLED BY */
/* */
/* Application */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
/* */
/**************************************************************************/
UINT _nxe_pppoe_server_enable(NX_PPPOE_SERVER *pppoe_server_ptr)
{
UINT status;
/* Check for invalid input pointers. */
if ((pppoe_server_ptr == NX_NULL) || (pppoe_server_ptr -> nx_pppoe_id != NX_PPPOE_SERVER_ID))
return(NX_PPPOE_SERVER_PTR_ERROR);
/* Make sure the data receive callback function is set before enable.
Setting this function by nx_pppoe_server_callback_notify_set() API. */
if (pppoe_server_ptr -> nx_pppoe_data_receive_notify == NX_NULL)
return(NX_PPPOE_SERVER_PTR_ERROR);
/* Call actual PPPoE server instance enable function. */
status = _nx_pppoe_server_enable(pppoe_server_ptr);
/* Return completion status. */
return(status);
}
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _nx_pppoe_server_enable PORTABLE C */
/* 6.1 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function enables the PPPoE Server feature. */
/* */
/* INPUT */
/* */
/* tx_mutex_get Obtain a protection mutex */
/* tx_mutex_put Release protection mutex */
/* tx_thread_resume Resume PPPoE helper thread */
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* _nx_pppoe_server_enable Actual PPPoE enable function */
/* */
/* CALLED BY */
/* */
/* Application */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
/* */
/**************************************************************************/
UINT _nx_pppoe_server_enable(NX_PPPOE_SERVER *pppoe_server_ptr)
{
/* Obtain the IP internal mutex before processing the IP event. */
tx_mutex_get(&(pppoe_server_ptr -> nx_pppoe_ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
/* Set the enabled flag. */
pppoe_server_ptr -> nx_pppoe_enabled = NX_TRUE;
/* Resume the PPPoE server thread. */
tx_thread_resume(&(pppoe_server_ptr -> nx_pppoe_thread));
/* Release the IP internal mutex. */
tx_mutex_put(&(pppoe_server_ptr -> nx_pppoe_ip_ptr -> nx_ip_protection));
/* Return success. */
return(NX_PPPOE_SERVER_SUCCESS);
}
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _nxe_pppoe_server_disable PORTABLE C */
/* 6.1 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function checks for errors in the PPPoE Server disable function*/
/* call. */
/* */
/* INPUT */
/* */
/* pppoe_server_ptr Pointer to PPPoE control block*/
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* _nx_pppoe_server_disable Actual PPPoE disable function */
/* */
/* CALLED BY */
/* */
/* Application */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
/* */
/**************************************************************************/
UINT _nxe_pppoe_server_disable(NX_PPPOE_SERVER *pppoe_server_ptr)
{
UINT status;
/* Check for invalid input pointers. */
if ((pppoe_server_ptr == NX_NULL) || (pppoe_server_ptr -> nx_pppoe_id != NX_PPPOE_SERVER_ID))
return(NX_PPPOE_SERVER_PTR_ERROR);
/* Call actual PPPoE server instance disable function. */
status = _nx_pppoe_server_disable(pppoe_server_ptr);
/* Return completion status. */
return(status);
}
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _nx_pppoe_server_disable PORTABLE C */
/* 6.1 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function disables the PPPoE Server feature. */
/* */
/* INPUT */
/* */
/* tx_mutex_get Obtain a protection mutex */
/* tx_mutex_put Release protection mutex */
/* tx_thread_suspend Suspend PPPoE helper thread */
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* _nx_pppoe_server_enable Actual PPPoE enable function */
/* */
/* CALLED BY */
/* */
/* Application */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
/* */
/**************************************************************************/
UINT _nx_pppoe_server_disable(NX_PPPOE_SERVER *pppoe_server_ptr)
{
/* Obtain the IP internal mutex before processing the IP event. */
tx_mutex_get(&(pppoe_server_ptr -> nx_pppoe_ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
/* Set the enabled flag. */
pppoe_server_ptr -> nx_pppoe_enabled = NX_FALSE;
/* Suspend the PPPoE server thread. */
tx_thread_suspend(&(pppoe_server_ptr -> nx_pppoe_thread));
/* Release the IP internal mutex. */
tx_mutex_put(&(pppoe_server_ptr -> nx_pppoe_ip_ptr -> nx_ip_protection));
/* Return success. */
return(NX_PPPOE_SERVER_SUCCESS);
}
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _nxe_pppoe_server_callback_notify_set PORTABLE C */
/* 6.1 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function checks for errors in the PPPoE Server disable function*/
/* call. */
/* */
/* INPUT */
/* */
/* pppoe_server_ptr Pointer to PPPoE control block*/
/* pppoe_discover_initiation_notify Routine to call when discovery*/
/* initiation data is received */
/* pppoe_discover_request_notify Routine to call when discovery*/
/* reques data is received */
/* pppoe_discover_terminate_notify Routine to call when discovery*/
/* terminate data is received */
/* pppoe_discover_terminate_confirm Routine to call when discovery*/
/* terminate data is sent */
/* pppoe_data_receive_notify Routine to call when session */
/* data is received */
/* pppoe_data_send_notify Routine to call when session */
/* data is sent */
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* _nx_pppoe_server_callback_notify_set Actual PPPoE callback set */
/* function */
/* */
/* CALLED BY */
/* */
/* Application */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
/* */
/**************************************************************************/
UINT _nxe_pppoe_server_callback_notify_set(NX_PPPOE_SERVER *pppoe_server_ptr,
VOID (* pppoe_discover_initiation_notify)(UINT session_index),
VOID (* pppoe_discover_request_notify)(UINT session_index, ULONG length, UCHAR *data),
VOID (* pppoe_discover_terminate_notify)(UINT session_index),
VOID (* pppoe_discover_terminate_confirm)(UINT session_index),
VOID (* pppoe_data_receive_notify)(UINT session_index, ULONG length, UCHAR *data, UINT packet_id),
VOID (* pppoe_data_send_notify)(UINT session_index, UCHAR *data))
{
UINT status;
/* Check for invalid input pointers. */
if ((pppoe_server_ptr == NX_NULL) || (pppoe_server_ptr -> nx_pppoe_id != NX_PPPOE_SERVER_ID))
return(NX_PPPOE_SERVER_PTR_ERROR);
/* Check to see if pppoe_data_receive_notify is set. */
if (pppoe_data_receive_notify == NX_NULL)
return(NX_PPPOE_SERVER_PTR_ERROR);
/* Call actual PPPoE service callback notify set function. */
status = _nx_pppoe_server_callback_notify_set(pppoe_server_ptr, pppoe_discover_initiation_notify, pppoe_discover_request_notify,
pppoe_discover_terminate_notify, pppoe_discover_terminate_confirm,
pppoe_data_receive_notify, pppoe_data_send_notify);
/* Return completion status. */
return(status);
}
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _nx_pppoe_server_callback_notify_set PORTABLE C */
/* 6.1 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function sets the callback notify functions. */
/* */
/* INPUT */
/* */
/* pppoe_server_ptr Pointer to PPPoE control block*/
/* pppoe_discover_initiation_notify Routine to call when discovery*/
/* initiation data is received */
/* pppoe_discover_request_notify Routine to call when discovery*/
/* reques data is received */
/* pppoe_discover_terminate_notify Routine to call when discovery*/
/* terminate data is received */
/* pppoe_discover_terminate_confirm Routine to call when discovery*/
/* terminate data is sent */
/* pppoe_data_receive_notify Routine to call when session */
/* data is received */
/* pppoe_data_send_notify Routine to call when session */
/* data is sent */
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* tx_mutex_get Obtain a protection mutex */
/* tx_mutex_put Release protection mutex */
/* */
/* CALLED BY */
/* */
/* Application */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
/* */
/**************************************************************************/
UINT _nx_pppoe_server_callback_notify_set(NX_PPPOE_SERVER *pppoe_server_ptr,
VOID (* pppoe_discover_initiation_notify)(UINT session_index),
VOID (* pppoe_discover_request_notify)(UINT session_index, ULONG length, UCHAR *data),
VOID (* pppoe_discover_terminate_notify)(UINT session_index),
VOID (* pppoe_discover_terminate_confirm)(UINT session_index),
VOID (* pppoe_data_receive_notify)(UINT session_index, ULONG length, UCHAR *data, UINT packet_id),
VOID (* pppoe_data_send_notify)(UINT session_index, UCHAR *data))
{
/* Obtain the IP internal mutex before processing the IP event. */
tx_mutex_get(&(pppoe_server_ptr -> nx_pppoe_ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
/* Install PPPoE notify function pointer */
pppoe_server_ptr -> nx_pppoe_discover_initiation_notify = pppoe_discover_initiation_notify;
pppoe_server_ptr -> nx_pppoe_discover_request_notify = pppoe_discover_request_notify;
pppoe_server_ptr -> nx_pppoe_discover_terminate_notify = pppoe_discover_terminate_notify;
pppoe_server_ptr -> nx_pppoe_discover_terminate_confirm = pppoe_discover_terminate_confirm;
pppoe_server_ptr -> nx_pppoe_data_receive_notify = pppoe_data_receive_notify;
pppoe_server_ptr -> nx_pppoe_data_send_notify = pppoe_data_send_notify;
/* Release the IP internal mutex. */
tx_mutex_put(&(pppoe_server_ptr -> nx_pppoe_ip_ptr -> nx_ip_protection));
/* Return success. */
return(NX_PPPOE_SERVER_SUCCESS);
}
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _nxe_pppoe_server_service_name_set PORTABLE C */
/* 6.1 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function checks for errors in the PPPoE service name set */
/* function call. */
/* */
/* INPUT */
/* */
/* pppoe_server_ptr Pointer to PPPoE control block*/
/* service_name Pointer to an array service */
/* names. Each service name */
/* must be Null-terminated */
/* string. */
/* service_name_count The counter of service names */
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* _nx_pppoe_server_service_name_set Actual PPPoE service name set */
/* function */
/* */
/* CALLED BY */
/* */
/* Application */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
/* */
/**************************************************************************/
UINT _nxe_pppoe_server_service_name_set(NX_PPPOE_SERVER *pppoe_server_ptr, UCHAR **service_name, UINT service_name_count)
{
UINT status;
/* Check for invalid input pointers. */
if ((pppoe_server_ptr == NX_NULL) || (pppoe_server_ptr -> nx_pppoe_id != NX_PPPOE_SERVER_ID))
return(NX_PPPOE_SERVER_PTR_ERROR);
/* Call actual PPPoE service name set function. */
status = _nx_pppoe_server_service_name_set(pppoe_server_ptr, service_name, service_name_count);
/* Return completion status. */
return(status);
}
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _nx_pppoe_server_service_name_set PORTABLE C */
/* 6.1 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function sets the the PPPoE service name. */
/* */
/* INPUT */
/* */
/* pppoe_server_ptr Pointer to PPPoE control block*/
/* service_name Pointer to an array service */
/* names. Each service name */
/* must be Null-terminated */
/* string. */
/* service_name_count The counter of service names */
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* tx_mutex_get Obtain a protection mutex */
/* tx_mutex_put Release protection mutex */
/* */
/* CALLED BY */
/* */
/* Application */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
/* */
/**************************************************************************/
UINT _nx_pppoe_server_service_name_set(NX_PPPOE_SERVER *pppoe_server_ptr, UCHAR **service_name, UINT service_name_count)
{
/* Obtain the IP internal mutex before processing the IP event. */
tx_mutex_get(&(pppoe_server_ptr -> nx_pppoe_ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
/* Setup service name pointer. */
pppoe_server_ptr -> nx_pppoe_service_name = service_name;
/* Setup service name count. */
pppoe_server_ptr -> nx_pppoe_service_name_count = service_name_count;
/* Release the IP internal mutex. */
tx_mutex_put(&(pppoe_server_ptr -> nx_pppoe_ip_ptr -> nx_ip_protection));
/* Return success. */
return(NX_PPPOE_SERVER_SUCCESS);
}
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _nxe_pppoe_server_session_send PORTABLE C */
/* 6.1 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function checks for errors in the PPPoE session data send */
/* function call. */
/* */
/* INPUT */
/* */
/* pppoe_server_ptr Pointer to PPPoE control block*/
/* session_index Session index */
/* data_ptr Session Data pointer */
/* data_length Length of Session Data */
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* _nx_pppoe_server_session_send Actual PPPoE Session data send*/
/* function */
/* */
/* CALLED BY */
/* */
/* Application */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
/* */
/**************************************************************************/
UINT _nxe_pppoe_server_session_send(NX_PPPOE_SERVER *pppoe_server_ptr, UINT session_index, UCHAR *data_ptr, UINT data_length)
{
UINT status;
/* Check for invalid input pointers. */
if ((pppoe_server_ptr == NX_NULL) || (pppoe_server_ptr -> nx_pppoe_id != NX_PPPOE_SERVER_ID) || (data_ptr == NX_NULL))
return(NX_PPPOE_SERVER_PTR_ERROR);
/* Check the service_name_count. */
if (data_length == 0)
return(NX_PPPOE_SERVER_PTR_ERROR);
/* Check to see if PPPoE is enabled. */
if (pppoe_server_ptr -> nx_pppoe_enabled != NX_TRUE)
return(NX_PPPOE_SERVER_NOT_ENABLED);
/* Check for invalid session index. */
if(session_index >= NX_PPPOE_SERVER_MAX_CLIENT_SESSION_NUMBER)
return(NX_PPPOE_SERVER_INVALID_SESSION);
/* Check to see if PPPoE session is established. */
if ((pppoe_server_ptr -> nx_pppoe_client_session[session_index].nx_pppoe_valid != NX_TRUE) ||
(pppoe_server_ptr -> nx_pppoe_client_session[session_index].nx_pppoe_session_id == 0))
return(NX_PPPOE_SERVER_SESSION_NOT_ESTABLISHED);
/* Call actual PPPoE session send function. */
status = _nx_pppoe_server_session_send(pppoe_server_ptr, session_index, data_ptr, data_length);
/* Return completion status. */
return(status);
}
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _nx_pppoe_server_session_send PORTABLE C */
/* 6.1 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function builds an PPPoE Session packet and calls the */
/* associated driver to send it out on the network. */
/* */
/* INPUT */
/* */
/* pppoe_server_ptr Pointer to PPPoE control block*/
/* session_index Session index */
/* data_ptr Session Data pointer */
/* data_length Length of Session Data */
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* tx_mutex_get Obtain a protection mutex */
/* tx_mutex_put Release protection mutex */
/* nx_packet_allocate Allocate a packet for the */
/* PPPoE Session */
/* nx_packet_release Release packet to packet pool */
/* nx_packet_data_append Copies the specified data */
/* _nx_pppoe_server_data_add Add PPPoE data */
/* _nx_pppoe_server_packet_send Send out PPPoE packet */
/* */
/* CALLED BY */
/* */
/* Application */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
/* */
/**************************************************************************/
UINT _nx_pppoe_server_session_send(NX_PPPOE_SERVER *pppoe_server_ptr, UINT session_index, UCHAR *data_ptr, UINT data_length)
{
NX_PPPOE_CLIENT_SESSION *client_session_ptr;
NX_PACKET *packet_ptr;
UCHAR *work_ptr;
UINT status;
/* Allocate a PPPoE packet. */
status = nx_packet_allocate(pppoe_server_ptr -> nx_pppoe_packet_pool_ptr, &packet_ptr, NX_PHYSICAL_HEADER, NX_PPPOE_SERVER_PACKET_TIMEOUT);
/* Was the packet allocation successful? */
if (status != NX_SUCCESS)
{
/* Return status. */
return(status);
}
/* Obtain the IP internal mutex. */
tx_mutex_get(&(pppoe_server_ptr -> nx_pppoe_ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
/* Set the client session pointer. */
client_session_ptr = &(pppoe_server_ptr -> nx_pppoe_client_session[session_index]);
/* Set the work pointer. */
work_ptr = packet_ptr -> nx_packet_prepend_ptr;
/* Added the PPPoE header. */
/*
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* | VER | TYPE | CODE | SESSION_ID |
* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* | LENGTH | payload
* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*/
/* Add version and type. */
_nx_pppoe_server_data_add(work_ptr + NX_PPPOE_SERVER_OFFSET_VER_TYPE, 1, NX_PPPOE_SERVER_VERSION_TYPE);
/* Add code. */
_nx_pppoe_server_data_add(work_ptr + NX_PPPOE_SERVER_OFFSET_CODE, 1, NX_PPPOE_SERVER_CODE_ZERO);
/* Add session id. */
_nx_pppoe_server_data_add(work_ptr + NX_PPPOE_SERVER_OFFSET_SESSION_ID, 2, client_session_ptr -> nx_pppoe_session_id);
/* Add length. */
_nx_pppoe_server_data_add(work_ptr + NX_PPPOE_SERVER_OFFSET_LENGTH, 2, data_length);
/* Update the pointer to add the payload of PPPoE. */
packet_ptr -> nx_packet_append_ptr += NX_PPPOE_SERVER_OFFSET_PAYLOAD;
packet_ptr -> nx_packet_length += NX_PPPOE_SERVER_OFFSET_PAYLOAD;
/* Release the mutex before a blocking call. */
tx_mutex_put(&(pppoe_server_ptr -> nx_pppoe_ip_ptr -> nx_ip_protection));
/* Append the data into PPPoE packet. */
status = nx_packet_data_append(packet_ptr, data_ptr, data_length, pppoe_server_ptr -> nx_pppoe_packet_pool_ptr, NX_PPPOE_SERVER_PACKET_TIMEOUT);
/* Was the packet allocation successful? */
if (status != NX_SUCCESS)
{
/* Relase the packet. */
nx_packet_release(packet_ptr);
/* Return status. */
return(status);
}
/* Regain obtain the IP internal mutex. */
tx_mutex_get(&(pppoe_server_ptr -> nx_pppoe_ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
/* Send PPPoE session packet. */
_nx_pppoe_server_packet_send(pppoe_server_ptr, client_session_ptr, packet_ptr, NX_LINK_PPPOE_SESSION_SEND);
/* Check the PPPoE send function. */
if (pppoe_server_ptr -> nx_pppoe_data_send_notify)
{
/* Call the function to send the data frame. */
pppoe_server_ptr -> nx_pppoe_data_send_notify(session_index, data_ptr);
}
/* Release the IP internal mutex. */
tx_mutex_put(&(pppoe_server_ptr -> nx_pppoe_ip_ptr -> nx_ip_protection));
/* Return success. */
return(NX_PPPOE_SERVER_SUCCESS);
}
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _nxe_pppoe_server_session_packet_send PORTABLE C */
/* 6.1 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function checks for errors in the PPPoE session packet send */
/* function call. */
/* */
/* INPUT */
/* */
/* pppoe_server_ptr Pointer to PPPoE control block*/
/* session_index Session index */
/* packet_ptr Pointer to packet to send */
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* _nx_pppoe_server_session_packet_send Actual PPPoE Session data send*/
/* function */
/* */
/* CALLED BY */
/* */
/* Application */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
/* */
/**************************************************************************/
UINT _nxe_pppoe_server_session_packet_send(NX_PPPOE_SERVER *pppoe_server_ptr, UINT session_index, NX_PACKET *packet_ptr)
{
UINT status;
/* Check for invalid packet. */
if (packet_ptr == NX_NULL)
{
return(NX_PPPOE_SERVER_PTR_ERROR);
}
/* Check for minimum packet length (PPP DATA Header). */
if (packet_ptr -> nx_packet_length < 2)
{
/* Release the packet. */
nx_packet_transmit_release(packet_ptr);
return(NX_PPPOE_SERVER_PACKET_PAYLOAD_ERROR);
}
/* Check for invalid input pointers. */
if ((pppoe_server_ptr == NX_NULL) || (pppoe_server_ptr -> nx_pppoe_id != NX_PPPOE_SERVER_ID))
{
/* Adjust the packet prepend to remove the PPP header. */
packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_prepend_ptr + 2;
packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length - 2;
/* Release the packet. */
nx_packet_transmit_release(packet_ptr);
return(NX_PPPOE_SERVER_PTR_ERROR);
}
/* Check to see if PPPoE is enabled. */
if (pppoe_server_ptr -> nx_pppoe_enabled != NX_TRUE)
{
/* Adjust the packet prepend to remove the PPP header. */
packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_prepend_ptr + 2;
packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length - 2;
/* Release the packet. */
nx_packet_transmit_release(packet_ptr);
return(NX_PPPOE_SERVER_NOT_ENABLED);
}
/* Check for invalid session index. */
if(session_index >= NX_PPPOE_SERVER_MAX_CLIENT_SESSION_NUMBER)
{
/* Adjust the packet prepend to remove the PPP header. */
packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_prepend_ptr + 2;
packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length - 2;
/* Release the packet. */
nx_packet_transmit_release(packet_ptr);
return(NX_PPPOE_SERVER_INVALID_SESSION);
}
/* Check to see if PPPoE session is established. */
if ((pppoe_server_ptr -> nx_pppoe_client_session[session_index].nx_pppoe_valid != NX_TRUE) ||
(pppoe_server_ptr -> nx_pppoe_client_session[session_index].nx_pppoe_session_id == 0))
{
/* Adjust the packet prepend to remove the PPP header. */
packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_prepend_ptr + 2;
packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length - 2;
/* Release the packet. */
nx_packet_transmit_release(packet_ptr);
return(NX_PPPOE_SERVER_SESSION_NOT_ESTABLISHED);
}
/* Call actual PPPoE session packet_send function. */
status = _nx_pppoe_server_session_packet_send(pppoe_server_ptr, session_index, packet_ptr);
/* Return completion status. */
return(status);
}
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _nx_pppoe_server_session_packet_send PORTABLE C */
/* 6.1 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function builds an PPPoE Session packet and calls the */
/* associated driver to send it out on the network. */
/* */
/* INPUT */
/* */
/* pppoe_server_ptr Pointer to PPPoE control block*/
/* session_index Session index */
/* data_ptr Session Data pointer */
/* data_length Length of Session Data */
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* tx_mutex_get Obtain a protection mutex */
/* tx_mutex_put Release protection mutex */
/* nx_packet_release Release packet to packet pool */
/* nx_packet_data_append Copies the specified data */
/* _nx_pppoe_server_data_add Add PPPoE data */
/* _nx_pppoe_server_packet_send Send out PPPoE packet */
/* */
/* CALLED BY */
/* */
/* Application */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
/* */
/**************************************************************************/
UINT _nx_pppoe_server_session_packet_send(NX_PPPOE_SERVER *pppoe_server_ptr, UINT session_index, NX_PACKET *packet_ptr)
{
NX_PPPOE_CLIENT_SESSION *client_session_ptr;
UCHAR *work_ptr;
/* Obtain the IP internal mutex. */
tx_mutex_get(&(pppoe_server_ptr -> nx_pppoe_ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
/* Check for an invalid packet prepend pointer. */
if ((packet_ptr -> nx_packet_prepend_ptr - packet_ptr -> nx_packet_data_start) < NX_PPPOE_SERVER_OFFSET_PAYLOAD)
{
/* Adjust the packet prepend to remove the PPP header. */
packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_prepend_ptr + 2;
packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length - 2;
/* Release the packet. */
nx_packet_transmit_release(packet_ptr);
/* Release the IP internal mutex. */
tx_mutex_put(&(pppoe_server_ptr -> nx_pppoe_ip_ptr -> nx_ip_protection));
/* Return error code. */
return(NX_PPPOE_SERVER_PACKET_PAYLOAD_ERROR);
}
/* Set the client session pointer. */
client_session_ptr = &(pppoe_server_ptr -> nx_pppoe_client_session[session_index]);
/* Set the work pointer. */
packet_ptr -> nx_packet_prepend_ptr -= NX_PPPOE_SERVER_OFFSET_PAYLOAD;
work_ptr = packet_ptr -> nx_packet_prepend_ptr;
/* Added the PPPoE header. */
/*
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* | VER | TYPE | CODE | SESSION_ID |
* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* | LENGTH | payload
* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*/
/* Add version and type. */
_nx_pppoe_server_data_add(work_ptr + NX_PPPOE_SERVER_OFFSET_VER_TYPE, 1, NX_PPPOE_SERVER_VERSION_TYPE);
/* Add code. */
_nx_pppoe_server_data_add(work_ptr + NX_PPPOE_SERVER_OFFSET_CODE, 1, NX_PPPOE_SERVER_CODE_ZERO);
/* Add session id. */
_nx_pppoe_server_data_add(work_ptr + NX_PPPOE_SERVER_OFFSET_SESSION_ID, 2, client_session_ptr -> nx_pppoe_session_id);
/* Add length. */
_nx_pppoe_server_data_add(work_ptr + NX_PPPOE_SERVER_OFFSET_LENGTH, 2, packet_ptr -> nx_packet_length);
/* Update the packet length. */
packet_ptr -> nx_packet_length += NX_PPPOE_SERVER_OFFSET_PAYLOAD;
/* Send PPPoE session packet. */
_nx_pppoe_server_packet_send(pppoe_server_ptr, client_session_ptr, packet_ptr, NX_LINK_PPPOE_SESSION_SEND);
/* Release the IP internal mutex. */
tx_mutex_put(&(pppoe_server_ptr -> nx_pppoe_ip_ptr -> nx_ip_protection));
/* Return success. */
return(NX_PPPOE_SERVER_SUCCESS);
}
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _nxe_pppoe_server_session_terminate PORTABLE C */
/* 6.1 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function checks for errors in the PPPoE session terminate */
/* function call. */
/* */
/* INPUT */
/* */
/* pppoe_server_ptr Pointer to PPPoE control block*/
/* session_index Session index */
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* _nx_pppoe_server_session_terminate Actual PPPoE Session terminate*/
/* function */
/* */
/* CALLED BY */
/* */
/* Application */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
/* */
/**************************************************************************/
UINT _nxe_pppoe_server_session_terminate(NX_PPPOE_SERVER *pppoe_server_ptr, UINT session_index)
{
UINT status;
/* Check for invalid input pointers. */
if ((pppoe_server_ptr == NX_NULL) || (pppoe_server_ptr -> nx_pppoe_id != NX_PPPOE_SERVER_ID))
return(NX_PPPOE_SERVER_PTR_ERROR);
/* Check to see if PPPoE is enabled. */
if (pppoe_server_ptr -> nx_pppoe_enabled != NX_TRUE)
return(NX_PPPOE_SERVER_NOT_ENABLED);
/* Check for invalid session index. */
if(session_index >= NX_PPPOE_SERVER_MAX_CLIENT_SESSION_NUMBER)
return(NX_PPPOE_SERVER_INVALID_SESSION);
/* Check to see if PPPoE session is established. */
if ((pppoe_server_ptr -> nx_pppoe_client_session[session_index].nx_pppoe_valid != NX_TRUE) ||
(pppoe_server_ptr -> nx_pppoe_client_session[session_index].nx_pppoe_session_id == 0))
return(NX_PPPOE_SERVER_SESSION_NOT_ESTABLISHED);
/* Call actual PPPoE session terminate function. */
status = _nx_pppoe_server_session_terminate(pppoe_server_ptr, session_index);
/* Return completion status. */
return(status);
}
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _nx_pppoe_server_session_terminate PORTABLE C */
/* 6.1 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function builds an PPPoE packet to terminate the session. */
/* */
/* INPUT */
/* */
/* pppoe_server_ptr Pointer to PPPoE control block*/
/* session_index Session index */
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* tx_mutex_get Obtain a protection mutex */
/* tx_mutex_put Release protection mutex */
/* _nx_pppoe_server_discovery_send Send out PPPoE packet */
/* _nx_pppoe_server_session_cleanup Cleanup PPPoE session */
/* */
/* CALLED BY */
/* */
/* Application */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
/* */
/**************************************************************************/
UINT _nx_pppoe_server_session_terminate(NX_PPPOE_SERVER *pppoe_server_ptr, UINT session_index)
{
NX_PPPOE_CLIENT_SESSION *client_session_ptr;
UINT status;
/* Obtain the IP internal mutex before processing the IP event. */
tx_mutex_get(&(pppoe_server_ptr -> nx_pppoe_ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
/* Set the client session pointer. */
client_session_ptr = &(pppoe_server_ptr -> nx_pppoe_client_session[session_index]);
/* Terminate the PPPoE session. */
status = _nx_pppoe_server_discovery_send(pppoe_server_ptr, client_session_ptr, NX_PPPOE_SERVER_CODE_PADT);
/* Check the status. */
if (status == NX_PPPOE_SERVER_SUCCESS)
{
/* Cleanup the session. */
_nx_pppoe_server_session_cleanup(client_session_ptr);
/* Check the PPPoE terminate confirm function. */
if (pppoe_server_ptr -> nx_pppoe_discover_terminate_confirm)
{
/* Call terminate confirm function. */
pppoe_server_ptr -> nx_pppoe_discover_terminate_confirm(session_index);
}
}
/* Release the IP internal mutex. */
tx_mutex_put(&(pppoe_server_ptr -> nx_pppoe_ip_ptr -> nx_ip_protection));
/* Return status. */
return(status);
}
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _nxe_pppoe_server_session_get PORTABLE C */
/* 6.1 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function checks for errors in the PPPoE session get function */
/* call. */
/* */
/* INPUT */
/* */
/* pppoe_server_ptr Pointer to PPPoE control block*/
/* session_index The index of Client Session */
/* client_mac_msw Client physical address MSW */
/* client_mac_lsw Client physical address LSW */
/* session_id Session ID */
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* _nx_pppoe_server_session_get Actual PPPoE Session get */
/* function */
/* */
/* CALLED BY */
/* */
/* Application */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
/* */
/**************************************************************************/
UINT _nxe_pppoe_server_session_get(NX_PPPOE_SERVER *pppoe_server_ptr, UINT session_index, ULONG *client_mac_msw, ULONG *client_mac_lsw, ULONG *session_id)
{
UINT status;
/* Check for invalid input pointers. */
if ((pppoe_server_ptr == NX_NULL) || (pppoe_server_ptr -> nx_pppoe_id != NX_PPPOE_SERVER_ID))
return(NX_PPPOE_SERVER_PTR_ERROR);
/* Check for invalid session index. */
if(session_index >= NX_PPPOE_SERVER_MAX_CLIENT_SESSION_NUMBER)
return(NX_PPPOE_SERVER_INVALID_SESSION);
/* Call actual PPPoE session get function. */
status = _nx_pppoe_server_session_get(pppoe_server_ptr, session_index, client_mac_msw, client_mac_lsw, session_id);
/* Return completion status. */
return(status);
}
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _nx_pppoe_server_session_get PORTABLE C */
/* 6.1 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function builds an PPPoE packet to get the session physical */
/* address and session id. */
/* */
/* INPUT */
/* */
/* pppoe_server_ptr Pointer to PPPoE control block*/
/* session_index The index of Client Session */
/* client_mac_msw Client physical address MSW */
/* client_mac_lsw Client physical address LSW */
/* session_id Session ID */
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* tx_mutex_get Obtain a protection mutex */
/* tx_mutex_put Release protection mutex */
/* */
/* CALLED BY */
/* */
/* Application */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
/* */
/**************************************************************************/
UINT _nx_pppoe_server_session_get(NX_PPPOE_SERVER *pppoe_server_ptr, UINT session_index, ULONG *client_mac_msw, ULONG *client_mac_lsw, ULONG *session_id)
{
/* Obtain the IP internal mutex before processing the IP event. */
tx_mutex_get(&(pppoe_server_ptr -> nx_pppoe_ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
/* Check to see if PPPoE session is established. */
if ((pppoe_server_ptr -> nx_pppoe_client_session[session_index].nx_pppoe_valid != NX_TRUE) ||
(pppoe_server_ptr -> nx_pppoe_client_session[session_index].nx_pppoe_session_id == 0))
{
/* Release the IP internal mutex. */
tx_mutex_put(&(pppoe_server_ptr -> nx_pppoe_ip_ptr -> nx_ip_protection));
return(NX_PPPOE_SERVER_SESSION_NOT_ESTABLISHED);
}
/* Yes, get the Client physical address MSW. */
if (client_mac_msw)
*client_mac_msw = pppoe_server_ptr -> nx_pppoe_client_session[session_index].nx_pppoe_physical_address_msw;
/* Yes, get the Client physical address LSW. */
if (client_mac_lsw)
*client_mac_lsw = pppoe_server_ptr -> nx_pppoe_client_session[session_index].nx_pppoe_physical_address_lsw;
/* Yes, get the Session ID. */
if (session_id)
*session_id = pppoe_server_ptr -> nx_pppoe_client_session[session_index].nx_pppoe_session_id;
/* Release the IP internal mutex. */
tx_mutex_put(&(pppoe_server_ptr -> nx_pppoe_ip_ptr -> nx_ip_protection));
/* Return status. */
return(NX_PPPOE_SERVER_SUCCESS);
}
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _nx_pppoe_server_packet_deferred_receive PORTABLE C */
/* 6.1 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function receives a packet from the link driver (usually the */
/* link driver's input ISR) and places it in the deferred receive */
/* packet queue. This moves the minimal receive packet processing */
/* from the ISR to the PPPoE helper thread. */
/* */
/* INPUT */
/* */
/* packet_ptr Pointer to packet to receive */
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* tx_event_flags_set Set events for PPPoE thread */
/* */
/* CALLED BY */
/* */
/* Application */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
/* */
/**************************************************************************/
VOID _nx_pppoe_server_packet_deferred_receive(NX_PACKET *packet_ptr)
{
TX_INTERRUPT_SAVE_AREA
/* Check to see if PPPoE instance is created. */
if (_nx_pppoe_server_created_ptr == NX_NULL)
{
/* Release the packet. */;
nx_packet_release(packet_ptr);
return;
}
/* Check to see if PPPoE is enabled. */
if (_nx_pppoe_server_created_ptr -> nx_pppoe_enabled != NX_TRUE)
{
/* Release the packet. */;
nx_packet_release(packet_ptr);
return;
}
/* Disable interrupts. */
TX_DISABLE
/* Check to see if the deferred processing queue is empty. */
if (_nx_pppoe_server_created_ptr -> nx_pppoe_deferred_received_packet_head)
{
/* Not empty, just place the packet at the end of the queue. */
(_nx_pppoe_server_created_ptr -> nx_pppoe_deferred_received_packet_tail) -> nx_packet_queue_next = packet_ptr;
packet_ptr -> nx_packet_queue_next = NX_NULL;
_nx_pppoe_server_created_ptr -> nx_pppoe_deferred_received_packet_tail = packet_ptr;
/* Restore interrupts. */
TX_RESTORE
}
else
{
/* Empty deferred receive processing queue. Just setup the head pointers and
set the event flags to ensure the PPPoE helper thread looks at the deferred processing
queue. */
_nx_pppoe_server_created_ptr -> nx_pppoe_deferred_received_packet_head = packet_ptr;
_nx_pppoe_server_created_ptr -> nx_pppoe_deferred_received_packet_tail = packet_ptr;
packet_ptr -> nx_packet_queue_next = NX_NULL;
/* Restore interrupts. */
TX_RESTORE
/* Wakeup PPPoE helper thread to process the PPPoE deferred receive. */
tx_event_flags_set(&(_nx_pppoe_server_created_ptr -> nx_pppoe_events), NX_PPPOE_SERVER_PACKET_RECEIVE_EVENT, TX_OR);
}
}
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _nx_pppoe_server_thread_entry PORTABLE C */
/* 6.1 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function is the entry point for each PPPoE's helper thread. */
/* The PPPoE helper thread is responsible for processing PPPoE packet. */
/* */
/* Note that the priority of this function is determined by the PPPoE */
/* create service. */
/* */
/* INPUT */
/* */
/* pppoe_server_ptr_value Pointer to PPPoE control block*/
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* tx_event_flags_get Suspend on event flags that */
/* are used to signal this */
/* thread what to do */
/* tx_mutex_get Obtain protection mutex */
/* tx_mutex_put Release protection mutex */
/* _nx_pppoe_server_packet_receive PPPoE receive packet */
/* processing */
/* nx_packet_release Release packet to packet pool */
/* (pppoe_link_driver) User supplied link driver */
/* */
/* CALLED BY */
/* */
/* ThreadX Scheduler */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
/* */
/**************************************************************************/
static VOID _nx_pppoe_server_thread_entry(ULONG pppoe_server_ptr_value)
{
TX_INTERRUPT_SAVE_AREA
#ifdef NX_PPPOE_SERVER_INITIALIZE_DRIVER_ENABLE
NX_IP_DRIVER driver_request;
#endif
NX_PPPOE_SERVER *pppoe_server_ptr;
NX_IP *ip_ptr;
NX_PACKET *packet_ptr;
ULONG pppoe_events;
#ifdef NX_PPPOE_SERVER_SESSION_CONTROL_ENABLE
UINT i;
#endif
/* Setup the PPPoE pointer. */
pppoe_server_ptr = (NX_PPPOE_SERVER *) pppoe_server_ptr_value;
/* Setup the IP pointer. */
ip_ptr = pppoe_server_ptr -> nx_pppoe_ip_ptr;
/* Obtain the IP internal mutex before calling the driver. */
tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
#ifdef NX_PPPOE_SERVER_INITIALIZE_DRIVER_ENABLE
/* Initialize and enable the hardware for physical interface. */
/* Is this a valid interface with a link driver associated with it? */
if((pppoe_server_ptr -> nx_pppoe_interface_ptr -> nx_interface_valid) && (pppoe_server_ptr -> nx_pppoe_link_driver_entry))
{
/* Yes; attach the interface to the device. */
driver_request.nx_ip_driver_ptr = ip_ptr;
driver_request.nx_ip_driver_command = NX_LINK_INTERFACE_ATTACH;
driver_request.nx_ip_driver_interface = pppoe_server_ptr -> nx_pppoe_interface_ptr;
(pppoe_server_ptr -> nx_pppoe_link_driver_entry) (&driver_request);
/* Call the link driver to initialize the hardware. Among other
responsibilities, the driver is required to provide the
Maximum Transfer Unit (MTU) for the physical layer. The MTU
should represent the actual physical layer transfer size
less the physical layer headers and trailers. */
driver_request.nx_ip_driver_ptr = ip_ptr;
driver_request.nx_ip_driver_command = NX_LINK_INITIALIZE;
(pppoe_server_ptr -> nx_pppoe_link_driver_entry) (&driver_request);
/* Call the link driver again to enable the interface. */
driver_request.nx_ip_driver_ptr = ip_ptr;
driver_request.nx_ip_driver_command = NX_LINK_ENABLE;
(pppoe_server_ptr -> nx_pppoe_link_driver_entry) (&driver_request);
/* Indicate to the IP software that IP to physical mapping
is not required. */
pppoe_server_ptr -> nx_pppoe_interface_ptr -> nx_interface_address_mapping_needed = NX_FALSE;
}
#endif
/* Loop to continue processing incoming bytes. */
while(NX_FOREVER)
{
/* Release the IP internal mutex. */
tx_mutex_put(&(ip_ptr -> nx_ip_protection));
/* Pickup IP event flags. */
tx_event_flags_get(&(pppoe_server_ptr -> nx_pppoe_events), NX_PPPOE_SERVER_ALL_EVENTS, TX_OR_CLEAR, &pppoe_events, NX_WAIT_FOREVER);
/* Obtain the IP internal mutex before processing the IP event. */
tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
/* Check for PPPoE event. */
if (pppoe_events & NX_PPPOE_SERVER_PACKET_RECEIVE_EVENT)
{
/* Loop to process all deferred packet requests. */
while (pppoe_server_ptr -> nx_pppoe_deferred_received_packet_head)
{
/* Remove the first packet and process it! */
/* Disable interrupts. */
TX_DISABLE
/* Pickup the first packet. */
packet_ptr = pppoe_server_ptr -> nx_pppoe_deferred_received_packet_head;
/* Move the head pointer to the next packet. */
pppoe_server_ptr -> nx_pppoe_deferred_received_packet_head = packet_ptr -> nx_packet_queue_next;
/* Check for end of deferred processing queue. */
if (pppoe_server_ptr -> nx_pppoe_deferred_received_packet_head == NX_NULL)
{
/* Yes, the queue is empty. Set the tail pointer to NULL. */
pppoe_server_ptr -> nx_pppoe_deferred_received_packet_tail = NX_NULL;
}
/* Restore interrupts. */
TX_RESTORE
/* Discard the chained packets. */
if (packet_ptr -> nx_packet_next)
{
nx_packet_release(packet_ptr);
continue;
}
/* Check for valid packet length. */
if (packet_ptr -> nx_packet_length < NX_PPPOE_SERVER_OFFSET_PAYLOAD)
{
/* Release the packet. */
nx_packet_release(packet_ptr);
return;
}
/* Check the packet interface. */
if ((packet_ptr -> nx_packet_ip_interface != NX_NULL) &&
(packet_ptr -> nx_packet_ip_interface != pppoe_server_ptr -> nx_pppoe_interface_ptr))
{
nx_packet_release(packet_ptr);
continue;
}
/* Call the actual PPPoE Server packet receive function. */
_nx_pppoe_server_packet_receive(pppoe_server_ptr, packet_ptr);
}
}
#ifdef NX_PPPOE_SERVER_SESSION_CONTROL_ENABLE
/* Check for PPPoE Session Receive event. */
if (pppoe_events & NX_PPPOE_SERVER_SESSION_RECEIVE_EVENT)
{
for(i = 0; i < NX_PPPOE_SERVER_MAX_CLIENT_SESSION_NUMBER; i ++)
{
/* Check if this session is valid. */
if (pppoe_server_ptr -> nx_pppoe_client_session[i].nx_pppoe_valid != NX_TRUE)
continue;
/* Check if this session is ready to receive the packet. */
if (pppoe_server_ptr -> nx_pppoe_client_session[i].nx_pppoe_packet_receive_stopped == NX_TRUE)
continue;
/* Check if this session queued the packets. */
if (pppoe_server_ptr -> nx_pppoe_client_session[i].nx_pppoe_deferred_received_packet_head)
{
/* Remove the first packet and process it! */
/* Disable interrupts. */
TX_DISABLE
/* Pickup the first packet. */
packet_ptr = pppoe_server_ptr -> nx_pppoe_client_session[i].nx_pppoe_deferred_received_packet_head;
/* Move the head pointer to the next packet. */
pppoe_server_ptr -> nx_pppoe_client_session[i].nx_pppoe_deferred_received_packet_head = packet_ptr -> nx_packet_queue_next;
/* Check for end of deferred processing queue. */
if (pppoe_server_ptr -> nx_pppoe_client_session[i].nx_pppoe_deferred_received_packet_head == NX_NULL)
{
/* Yes, the queue is empty. Set the tail pointer to NULL. */
pppoe_server_ptr -> nx_pppoe_client_session[i].nx_pppoe_deferred_received_packet_tail = NX_NULL;
}
/* Restore interrupts. */
TX_RESTORE
/* Set the flag to stop receive the next packet. */
pppoe_server_ptr -> nx_pppoe_client_session[i].nx_pppoe_packet_receive_stopped = NX_TRUE;
/* Check the PPPoE receive function. */
if (_nx_pppoe_server_created_ptr -> nx_pppoe_data_receive_notify)
{
/* Call the function to receive the data frame. */
_nx_pppoe_server_created_ptr -> nx_pppoe_data_receive_notify(i, packet_ptr -> nx_packet_length, packet_ptr -> nx_packet_prepend_ptr, (UINT)(packet_ptr));
}
}
}
}
#endif
}
}
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _nx_pppoe_server_packet_receive PORTABLE C */
/* 6.1 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function receives a PPPoE packet from the PPPoE deferred */
/* processing queue. */
/* */
/* INPUT */
/* */
/* pppoe_server_ptr Pointer to PPPoE control block*/
/* packet_ptr Pointer to packet to receive */
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* nx_packet_release Release packet to packet pool */
/* _nx_pppoe_server_data_get Get the PPPoE data */
/* _nx_pppoe_server_discovery_packet_process */
/* Process discovery packet */
/* _nx_pppoe_server_session_packet_process */
/* Process session packet */
/* */
/* CALLED BY */
/* */
/* _nx_pppoe_server_thread_entry */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
/* */
/**************************************************************************/
VOID _nx_pppoe_server_packet_receive(NX_PPPOE_SERVER *pppoe_server_ptr, NX_PACKET *packet_ptr)
{
UCHAR *ethernet_header_ptr;
ULONG server_mac_msw;
ULONG server_mac_lsw;
ULONG client_mac_msw;
ULONG client_mac_lsw;
UINT ethernet_type;
UINT is_broadcast = NX_FALSE;
/* Set up UCHAR pointer to ethernet header to extract client hardware address
which we will use as the client's unique identifier. */
ethernet_header_ptr = packet_ptr -> nx_packet_prepend_ptr - NX_PPPOE_SERVER_ETHER_HEADER_SIZE;
/* Pickup the MSW and LSW of the destination MAC address. */
server_mac_msw = (((ULONG) ethernet_header_ptr[0]) << 8) | ((ULONG) ethernet_header_ptr[1]);
server_mac_lsw = (((ULONG) ethernet_header_ptr[2]) << 24) | (((ULONG) ethernet_header_ptr[3]) << 16) |
(((ULONG) ethernet_header_ptr[4]) << 8) | ((ULONG) ethernet_header_ptr[5]);
/* Check the server hardware (mac address) field is filled in. */
if ((server_mac_msw == 0) && (server_mac_lsw == 0))
{
/* Release the packet. */
nx_packet_release(packet_ptr);
return;
}
/* Check if it is a broadcast message. */
if ((server_mac_msw == 0xFFFF) && (server_mac_lsw == 0xFFFFFFFF))
is_broadcast = NX_TRUE;
/* Pickup the MSW and LSW of the source MAC address. */
client_mac_msw = (((ULONG) ethernet_header_ptr[6]) << 8) | ((ULONG) ethernet_header_ptr[7]);
client_mac_lsw = (((ULONG) ethernet_header_ptr[8]) << 24) | (((ULONG) ethernet_header_ptr[9]) << 16) |
(((ULONG) ethernet_header_ptr[10]) << 8) | ((ULONG) ethernet_header_ptr[11]);
/* Check the client hardware (mac address) field is filled in. */
if ((client_mac_msw == 0) && (client_mac_lsw == 0))
{
/* Release the packet. */
nx_packet_release(packet_ptr);
return;
}
/* Get the ethernet type. */
ethernet_type = _nx_pppoe_server_data_get(ethernet_header_ptr + 12, 2);
/* Process the packet according to packet type. */
if(ethernet_type == NX_PPPOE_SERVER_ETHER_TYPE_DISCOVERY)
{
/* Process the discovery packet. */
_nx_pppoe_server_discovery_packet_process(pppoe_server_ptr, packet_ptr, client_mac_msw, client_mac_lsw, is_broadcast);
}
else if(ethernet_type == NX_PPPOE_SERVER_ETHER_TYPE_SESSION)
{
/* Session Stage, all Ethernet packets are unicast. */
if (is_broadcast == NX_TRUE)
{
/* Release the packet. */
nx_packet_release(packet_ptr);
return;
}
/* Process the session packet. */
_nx_pppoe_server_session_packet_process(pppoe_server_ptr, packet_ptr, client_mac_msw, client_mac_lsw);
}
else
{
/* Relase the packet. */
nx_packet_release(packet_ptr);
}
return;
}
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _nx_pppoe_server_discovery_packet_process PORTABLE C */
/* 6.1 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function processes an incoming discovery packet. */
/* */
/* INPUT */
/* */
/* pppoe_server_ptr Pointer to PPPoE control block*/
/* packet_ptr Pointer to packet to receive */
/* client_mac_msw Client physical address MSW */
/* client_mac_lsw Client physical address LSW */
/* is_broadcast Broadcast flag */
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* nx_packet_release Release packet to packet pool */
/* _nx_pppoe_server_data_get Get the PPPoE data */
/* _nx_pppoe_server_tag_process Process PPPoE tags */
/* _nx_pppoe_server_discovery_send Send discovery packet */
/* _nx_pppoe_server_session_find Find the PPPoE session */
/* _nx_pppoe_server_session_cleanup Cleanup the PPPoE session */
/* */
/* CALLED BY */
/* */
/* _nx_pppoe_server_packet_receive Receive the PPPoE packet */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), improved */
/* packet length verification, */
/* resulting in version 6.1 */
/* */
/**************************************************************************/
VOID _nx_pppoe_server_discovery_packet_process(NX_PPPOE_SERVER *pppoe_server_ptr, NX_PACKET *packet_ptr, ULONG client_mac_msw, ULONG client_mac_lsw, UINT is_broadcast)
{
UCHAR *pppoe_header_ptr;
ULONG ver_type;
ULONG code;
ULONG session_id;
ULONG length;
UINT status;
UCHAR *tag_ptr;
UINT session_index = 0;
NX_PPPOE_CLIENT_SESSION *client_session_ptr = NX_NULL;
/* Setup the PPPoE header. */
pppoe_header_ptr = packet_ptr -> nx_packet_prepend_ptr;
/* Pickup the version and type. */
ver_type = _nx_pppoe_server_data_get(pppoe_header_ptr + NX_PPPOE_SERVER_OFFSET_VER_TYPE, 1);
/* Check the version and type. */
if (ver_type != NX_PPPOE_SERVER_VERSION_TYPE)
{
/* Release the packet. */
nx_packet_release(packet_ptr);
return;
}
/* Pickup the code. */
code = _nx_pppoe_server_data_get(pppoe_header_ptr + NX_PPPOE_SERVER_OFFSET_CODE, 1);
/* Check the code. */
if ((code != NX_PPPOE_SERVER_CODE_PADI) &&
(code != NX_PPPOE_SERVER_CODE_PADR) &&
(code != NX_PPPOE_SERVER_CODE_PADT))
{
/* Release the packet. */
nx_packet_release(packet_ptr);
return;
}
/* For PADI, the destination address should be broadcast.
For PADR and PART, the destination address should be unicast. */
if (((code == NX_PPPOE_SERVER_CODE_PADI) && (is_broadcast != NX_TRUE)) ||
((code != NX_PPPOE_SERVER_CODE_PADI) && (is_broadcast == NX_TRUE)))
{
/* Release the packet. */
nx_packet_release(packet_ptr);
return;
}
/* Pickup the session id. */
session_id = _nx_pppoe_server_data_get(pppoe_header_ptr + NX_PPPOE_SERVER_OFFSET_SESSION_ID, 2);
/* Check the session id.
Session ID must be zero for PADI and PADR,
Session ID must be not zero for PADT. */
if (((code != NX_PPPOE_SERVER_CODE_PADT) && (session_id != 0)) ||
((code == NX_PPPOE_SERVER_CODE_PADT) && (session_id == 0)))
{
/* Release the packet. */
nx_packet_release(packet_ptr);
return;
}
/* Find the PPPoE Session. */
status = _nx_pppoe_server_session_find(pppoe_server_ptr, client_mac_msw, client_mac_lsw, session_id, &session_index, &client_session_ptr);
/* Check the status. */
if (status)
{
/* Release the packet. */
nx_packet_release(packet_ptr);
return;
}
/* Pickup the length of tags. */
length = _nx_pppoe_server_data_get(pppoe_header_ptr + NX_PPPOE_SERVER_OFFSET_LENGTH, 2);
/* Check for valid payload. */
if (length + NX_PPPOE_SERVER_OFFSET_PAYLOAD > packet_ptr -> nx_packet_length)
{
/* Release the packet. */
nx_packet_release(packet_ptr);
return;
}
/* Set the tag pointer. */
tag_ptr = pppoe_header_ptr + NX_PPPOE_SERVER_OFFSET_PAYLOAD;
/* Process the tag. */
status = _nx_pppoe_server_tag_process(pppoe_server_ptr, client_session_ptr, code, tag_ptr, length);
/* Now we can release the packet. */
nx_packet_release(packet_ptr);
/* Check the status. */
if (status)
{
/* If the Access Concentrator does not like the Service-Name in the PADR,
then it MUST reply with a PADS containing a TAG of TAG_TYPE Service-Name-Error (and any number of other TAG types).
In this case the SESSION_ID MUST be set to 0x0000. RFC2516, Section5.4, Page6. */
if ((status == NX_PPPOE_SERVER_SERVICE_NAME_ERROR) && (code == NX_PPPOE_SERVER_CODE_PADR))
{
/* Clear the session id. */
client_session_ptr -> nx_pppoe_session_id = 0;
/* Send PADS. */
_nx_pppoe_server_discovery_send(pppoe_server_ptr, client_session_ptr, NX_PPPOE_SERVER_CODE_PADS);
}
/* Cleanup the PPPoE session. */
_nx_pppoe_server_session_cleanup(client_session_ptr);
return;
}
/* Check the code value. */
if (code == NX_PPPOE_SERVER_CODE_PADI)
{
/* It is PPPoE Active Discovery Initiation packet. */
if (pppoe_server_ptr -> nx_pppoe_discover_initiation_notify)
{
/* Call discover initiation notify function. */
pppoe_server_ptr -> nx_pppoe_discover_initiation_notify(session_index);
#ifdef NX_PPPOE_SERVER_SESSION_CONTROL_ENABLE
/* Send PPPoE Active Discover Offer packet in PppDiscoverCnf(). */
return;
#endif
}
/* Send PPPoE Active Discovery Offer packet. */
_nx_pppoe_server_discovery_send(pppoe_server_ptr, client_session_ptr, NX_PPPOE_SERVER_CODE_PADO);
}
else if (code == NX_PPPOE_SERVER_CODE_PADR)
{
/* Generate the unique session id. */
if (client_session_ptr -> nx_pppoe_session_id == 0)
{
/* The Session ID should not be zero and 0xFFFF.
RFC2516, Section4, Page4. */
if ((pppoe_server_ptr -> nx_pppoe_session_id == 0) ||
(pppoe_server_ptr -> nx_pppoe_session_id == 0xFFFF))
pppoe_server_ptr -> nx_pppoe_session_id = 1;
/* Setup the session id. */
client_session_ptr -> nx_pppoe_session_id = pppoe_server_ptr -> nx_pppoe_session_id;
/* Update the session id for next client session. */
pppoe_server_ptr -> nx_pppoe_session_id++;
}
/* It is PPPoE Active Discovery Request packet. */
if (pppoe_server_ptr -> nx_pppoe_discover_request_notify)
{
/* Call discover reqest notify function. */
if (client_session_ptr -> nx_pppoe_service_name == NX_NULL)
{
pppoe_server_ptr -> nx_pppoe_discover_request_notify(session_index, 0, NX_NULL);
}
else
{
/* Check service name length. */
_nx_utility_string_length_check((char*)client_session_ptr -> nx_pppoe_service_name, (UINT *)&length, NX_MAX_STRING_LENGTH);
pppoe_server_ptr -> nx_pppoe_discover_request_notify(session_index, length, client_session_ptr -> nx_pppoe_service_name);
}
#ifdef NX_PPPOE_SERVER_SESSION_CONTROL_ENABLE
/* Send PPPoE Active Discover Session-confirmation packet in PppOpenCnf(). */
return;
#endif
}
/* Send PPPoE Active Discovery Session-confirmation packet. */
_nx_pppoe_server_discovery_send(pppoe_server_ptr, client_session_ptr, NX_PPPOE_SERVER_CODE_PADS);
}
else if (code == NX_PPPOE_SERVER_CODE_PADT)
{
#ifndef NX_PPPOE_SERVER_SESSION_CONTROL_ENABLE
/* Cleanup the PPPoE session. */
_nx_pppoe_server_session_cleanup(client_session_ptr);
#endif
/* It is PPPoE Active Discovery Terminate packet. */
if (pppoe_server_ptr -> nx_pppoe_discover_terminate_notify)
{
/* Call discover terminate notify function. */
pppoe_server_ptr -> nx_pppoe_discover_terminate_notify(session_index);
}
}
}
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _nx_pppoe_server_session_packet_process PORTABLE C */
/* 6.1 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function processes an incoming session packet. */
/* */
/* INPUT */
/* */
/* pppoe_server_ptr Pointer to PPPoE control block*/
/* packet_ptr Pointer to packet to receive */
/* client_mac_msw Client physical address MSW */
/* client_mac_lsw Client physical address LSW */
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* nx_packet_release Release packet to packet pool */
/* _nx_pppoe_server_data_get Get the PPPoE data */
/* _nx_pppoe_server_session_find Find the PPPoE session */
/* */
/* CALLED BY */
/* */
/* _nx_pppoe_server_packet_receive Receive the PPPoE packet */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
/* */
/**************************************************************************/
static VOID _nx_pppoe_server_session_packet_process(NX_PPPOE_SERVER *pppoe_server_ptr, NX_PACKET *packet_ptr, ULONG client_mac_msw, ULONG client_mac_lsw)
{
UCHAR *pppoe_header_ptr;
ULONG ver_type;
ULONG code;
ULONG session_id;
ULONG length;
UINT status;
UINT session_index = 0;
NX_PPPOE_CLIENT_SESSION *client_session_ptr = NX_NULL;
/* Setup the PPPoE header. */
pppoe_header_ptr = packet_ptr -> nx_packet_prepend_ptr;
/* Pickup the version and type. */
ver_type = _nx_pppoe_server_data_get(pppoe_header_ptr + NX_PPPOE_SERVER_OFFSET_VER_TYPE, 1);
/* Check the version and type. */
if (ver_type != NX_PPPOE_SERVER_VERSION_TYPE)
{
/* Release the packet. */
nx_packet_release(packet_ptr);
return;
}
/* Pickup the code. */
code = _nx_pppoe_server_data_get(pppoe_header_ptr + NX_PPPOE_SERVER_OFFSET_CODE, 1);
/* Check the code. */
if (code != NX_PPPOE_SERVER_CODE_ZERO)
{
/* Release the packet. */
nx_packet_release(packet_ptr);
return;
}
/* Pickup the session id. */
session_id = _nx_pppoe_server_data_get(pppoe_header_ptr + NX_PPPOE_SERVER_OFFSET_SESSION_ID, 2);
/* Check the session id. */
if (session_id == 0)
{
/* Release the packet. */
nx_packet_release(packet_ptr);
return;
}
/* Setup the prepend pointer to point the payload of PPPoE. */
packet_ptr -> nx_packet_prepend_ptr += NX_PPPOE_SERVER_OFFSET_PAYLOAD;
packet_ptr -> nx_packet_length -= NX_PPPOE_SERVER_OFFSET_PAYLOAD;
/* Look up the PPPoE session by physical address and interface index in Client Records table. */
status = _nx_pppoe_server_session_find(pppoe_server_ptr, client_mac_msw, client_mac_lsw, session_id, &session_index, &client_session_ptr);
/* Check the status. */
if (status)
{
/* Release the packet. */
nx_packet_release(packet_ptr);
return;
}
/* Pickup the length of payload. */
length = _nx_pppoe_server_data_get(pppoe_header_ptr + NX_PPPOE_SERVER_OFFSET_LENGTH, 2);
/* Check for valid payload. */
if (length > packet_ptr -> nx_packet_length)
{
/* Release the packet. */
nx_packet_release(packet_ptr);
return;
}
/* Remove the Ethernet padding. */
if (length < packet_ptr -> nx_packet_length)
{
packet_ptr -> nx_packet_append_ptr -= (packet_ptr -> nx_packet_length - length);
packet_ptr -> nx_packet_length -= (packet_ptr -> nx_packet_length - length);
}
#ifdef NX_PPPOE_SERVER_SESSION_CONTROL_ENABLE
/* Check to see if the deferred processing queue is empty. */
if (client_session_ptr -> nx_pppoe_deferred_received_packet_head)
{
/* Not empty, just place the packet at the end of the queue. */
(client_session_ptr -> nx_pppoe_deferred_received_packet_tail) -> nx_packet_queue_next = packet_ptr;
packet_ptr -> nx_packet_queue_next = NX_NULL;
client_session_ptr -> nx_pppoe_deferred_received_packet_tail = packet_ptr;
/* Return. */
return;
}
else
{
/* Check the packet receive flag. */
if (client_session_ptr -> nx_pppoe_packet_receive_stopped == NX_TRUE)
{
/* Empty deferred receive processing queue. Just setup the head pointers and
set the event flags to ensure the PPPoE helper thread looks at the deferred processing queue. */
client_session_ptr -> nx_pppoe_deferred_received_packet_head = packet_ptr;
client_session_ptr -> nx_pppoe_deferred_received_packet_tail = packet_ptr;
packet_ptr -> nx_packet_queue_next = NX_NULL;
/* Return. */
return;
}
}
/* Set the flag to stop receive the next packet. */
client_session_ptr -> nx_pppoe_packet_receive_stopped = NX_TRUE;
#endif
/* Check the PPPoE receive function. */
if (pppoe_server_ptr -> nx_pppoe_data_receive_notify)
{
/* Call the function to receive the data frame.
Notice: the receive function must release this packet. */
pppoe_server_ptr -> nx_pppoe_data_receive_notify(session_index, length, packet_ptr -> nx_packet_prepend_ptr, (UINT)(packet_ptr));
}
else
{
/* Release the packet. */
nx_packet_release(packet_ptr);
}
return;
}
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _nx_pppoe_server_discovery_send PORTABLE C */
/* 6.1.4 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function sends a PPPoE discovery packet. */
/* */
/* INPUT */
/* */
/* pppoe_server_ptr Pointer to PPPoE control block*/
/* client_session_ptr Pointer to Client Session */
/* code PPPoE code */
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* tx_mutex_get Obtain a protection mutex */
/* tx_mutex_put Release protection mutex */
/* nx_packet_allocate Allocate a packet for the */
/* PPPoE Discovery */
/* nx_packet_release Release packet to packet pool */
/* _nx_pppoe_server_data_add Add PPPoE data */
/* _nx_pppoe_server_tag_string_add Add PPPoE tag */
/* _nx_pppoe_server_packet_send Send out PPPoE packet */
/* _nx_pppoe_server_session_find Find the PPPoE session */
/* */
/* CALLED BY */
/* */
/* _nx_pppoe_server_session_terminate Terminate the PPPoE session */
/* _nx_pppoe_server_discovery_packet_process */
/* Process PPPoE Discovery packet*/
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
/* 02-02-2021 Yuxin Zhou Modified comment(s), */
/* fixed the compiler errors, */
/* resulting in version 6.1.4 */
/* */
/**************************************************************************/
static UINT _nx_pppoe_server_discovery_send(NX_PPPOE_SERVER *pppoe_server_ptr, NX_PPPOE_CLIENT_SESSION *client_session_ptr, UINT code)
{
NX_PACKET *packet_ptr;
UCHAR *work_ptr;
UINT status;
UINT index = 0;
UINT tag_length;
UINT service_name_index = 0;
#ifdef NX_PPPOE_SERVER_SESSION_CONTROL_ENABLE
UCHAR *service_name_ptr;
#endif
/* Release the mutex before a blocking call. */
tx_mutex_put(&(pppoe_server_ptr -> nx_pppoe_ip_ptr -> nx_ip_protection));
/* Allocate a PPPoE packet. */
status = nx_packet_allocate(pppoe_server_ptr -> nx_pppoe_packet_pool_ptr, &packet_ptr, NX_PHYSICAL_HEADER, NX_PPPOE_SERVER_PACKET_TIMEOUT);
/* Was the packet allocation successful? */
if (status != NX_SUCCESS)
{
/* Return status. */
return(status);
}
/* Obtain the IP internal mutex. */
tx_mutex_get(&(pppoe_server_ptr -> nx_pppoe_ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
/* Set the work pointer. */
work_ptr = packet_ptr -> nx_packet_prepend_ptr;
/* First skip the PPPoE header. */
index += NX_PPPOE_SERVER_OFFSET_PAYLOAD;
/* The PPPoE payload contains zero or more TAGs. A TAG is a TLV (type-length-value) construct and is defined as follows. */
/* 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* | TAG_TYPE | TAG_LENGTH |
* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* | TAG_VALUE ...
* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*/
/* Add the PPPoE tags. */
if (code == NX_PPPOE_SERVER_CODE_PADO)
{
/* The PADO packet MUST contain one AC-Name TAG containing the Access Concentrator's name. RFC2516, Section 5.2, Page6. */
/* Added the AC-Name tag. */
if (pppoe_server_ptr -> nx_pppoe_ac_name)
{
_nx_pppoe_server_tag_string_add(work_ptr, NX_PPPOE_SERVER_TAG_TYPE_AC_NAME, pppoe_server_ptr -> nx_pppoe_ac_name_length, (UCHAR *)(pppoe_server_ptr -> nx_pppoe_ac_name), &index);
}
else
{
/* If user does not separately set Access Concentrator name, will use PPPoE server name as Access Concentrator name.*/
_nx_pppoe_server_tag_string_add(work_ptr, NX_PPPOE_SERVER_TAG_TYPE_AC_NAME, pppoe_server_ptr -> nx_pppoe_name_length, (UCHAR *)(pppoe_server_ptr -> nx_pppoe_name), &index);
}
/* The PADO packet MUST contain a Service-Name TAG identical to the one in the PADI,
and any number of other Service-Name TAGs indicating other services. RFC2516, Section 5.2, Page6. */
/* Added a Service-Name TAG identical to the one in the PADI. */
if (client_session_ptr -> nx_pppoe_service_name)
{
#ifdef NX_PPPOE_SERVER_SESSION_CONTROL_ENABLE
/* Set the service name pointer. */
service_name_ptr = client_session_ptr -> nx_pppoe_service_name;
/* Loop to add service name that user configured. */
while(service_name_index < client_session_ptr -> nx_pppoe_service_name_length)
{
/* Get the service name. */
if (_nx_utility_string_length_check((char *)(service_name_ptr), &tag_length, NX_MAX_STRING_LENGTH))
{
nx_packet_release(packet_ptr);
return(NX_PPPOE_SERVER_SERVICE_NAME_ERROR);
}
/* Added the Service-Name tag. */
_nx_pppoe_server_tag_string_add(work_ptr, NX_PPPOE_SERVER_TAG_TYPE_SERVICE_NAME, tag_length, service_name_ptr, &index);
/* Update the service name pointer, length + null-terminated. */
service_name_ptr += (tag_length + 1);
service_name_index += (tag_length + 1);
}
#else
/* Calculate the name length. */
if (_nx_utility_string_length_check((char *)(client_session_ptr -> nx_pppoe_service_name), &tag_length, NX_MAX_STRING_LENGTH))
{
nx_packet_release(packet_ptr);
return(NX_PPPOE_SERVER_SERVICE_NAME_ERROR);
}
/* Added the Service-Name tag. */
_nx_pppoe_server_tag_string_add(work_ptr, NX_PPPOE_SERVER_TAG_TYPE_SERVICE_NAME, tag_length, client_session_ptr -> nx_pppoe_service_name, &index);
#endif
}
else
{
/* Added the Service-Name tag. */
_nx_pppoe_server_tag_string_add(work_ptr, NX_PPPOE_SERVER_TAG_TYPE_SERVICE_NAME, 0, NX_NULL, &index);
}
#ifndef NX_PPPOE_SERVER_SESSION_CONTROL_ENABLE
/* Add any number of other Service-Name TAGs indicating other services. */
if (pppoe_server_ptr -> nx_pppoe_service_name_count)
{
/* The PADO packet can contain any number of Service-Name TAGs. */
for (service_name_index = 0; service_name_index < pppoe_server_ptr -> nx_pppoe_service_name_count; service_name_index ++)
{
/* Check if this Service-Name has been added. */
if (pppoe_server_ptr -> nx_pppoe_service_name[service_name_index] == client_session_ptr -> nx_pppoe_service_name)
continue;
/* Calculate the name length. */
if (_nx_utility_string_length_check((char *)(pppoe_server_ptr -> nx_pppoe_service_name[service_name_index]), &tag_length, NX_MAX_STRING_LENGTH))
{
nx_packet_release(packet_ptr);
return(NX_PPPOE_SERVER_SERVICE_NAME_ERROR);
}
/* Added the Service-Name tag. */
_nx_pppoe_server_tag_string_add(work_ptr, NX_PPPOE_SERVER_TAG_TYPE_SERVICE_NAME, tag_length, (UCHAR *)(pppoe_server_ptr -> nx_pppoe_service_name[service_name_index]), &index);
}
}
#endif
/* If the Access Concentrator receives this Host-Uniq TAG, it MUST include the TAG unmodified in associated PADO or PADS response.
RFC2516, Appendix A, Host-Uniq. */
if (client_session_ptr -> nx_pppoe_host_uniq_size)
{
/* Added the Host-Uniq. */
_nx_pppoe_server_tag_string_add(work_ptr, NX_PPPOE_SERVER_TAG_TYPE_HOST_UNIQ, client_session_ptr -> nx_pppoe_host_uniq_size, client_session_ptr -> nx_pppoe_host_uniq, &index);
}
/* If either the Host or Access Concentrator receives this Relay-Session-Id TAG, they MUST include it unmodified in any discovery packet they send as a response.
RFC2516, Appendix A, Relay-Session-Id. */
if (client_session_ptr -> nx_pppoe_relay_session_id_size)
{
/* Added the Host-Uniq. */
_nx_pppoe_server_tag_string_add(work_ptr, NX_PPPOE_SERVER_TAG_TYPE_RELAY_SESSION_ID, client_session_ptr -> nx_pppoe_relay_session_id_size, client_session_ptr -> nx_pppoe_relay_session_id, &index);
}
}
else if (code == NX_PPPOE_SERVER_CODE_PADS)
{
/* Check the error. */
if (client_session_ptr -> nx_pppoe_error_flag & NX_PPPOE_SERVER_ERROR_SERVICE_NAME)
{
/* Added Service-Name-Error tag. */
_nx_pppoe_server_tag_string_add(work_ptr, NX_PPPOE_SERVER_TAG_TYPE_SERVICE_NAME_ERROR, 0, NX_NULL, &index);
}
/* The PADS packet MUST contain one exactly one TAG of TAG_TYPE Service-Name. RFC2516, Section 5.4, Page6 */
/* Check the service name. */
if (client_session_ptr -> nx_pppoe_service_name)
{
/* Calculate the name length. */
if (_nx_utility_string_length_check((char *)(client_session_ptr -> nx_pppoe_service_name), &tag_length, NX_MAX_STRING_LENGTH))
{
nx_packet_release(packet_ptr);
return(NX_PPPOE_SERVER_SERVICE_NAME_ERROR);
}
/* Added the Service-Name tag. */
_nx_pppoe_server_tag_string_add(work_ptr, NX_PPPOE_SERVER_TAG_TYPE_SERVICE_NAME, tag_length, client_session_ptr -> nx_pppoe_service_name, &index);
}
else
{
/* Added the Service-Name tag. */
_nx_pppoe_server_tag_string_add(work_ptr, NX_PPPOE_SERVER_TAG_TYPE_SERVICE_NAME, 0, NX_NULL, &index);
}
/* If the Access Concentrator receives this Host-Uniq TAG, it MUST include the TAG unmodified in associated PADO or PADS response.
RFC2516, Appendix A, Host-Uniq. */
if (client_session_ptr -> nx_pppoe_host_uniq_size)
{
/* Added the Host-Uniq. */
_nx_pppoe_server_tag_string_add(work_ptr, NX_PPPOE_SERVER_TAG_TYPE_HOST_UNIQ, client_session_ptr -> nx_pppoe_host_uniq_size, client_session_ptr -> nx_pppoe_host_uniq, &index);
}
/* If either the Host or Access Concentrator receives this Relay-Session-Id TAG, they MUST include it unmodified in any discovery packet they send as a response.
RFC2516, Appendix A, Relay-Session-Id. */
if (client_session_ptr -> nx_pppoe_relay_session_id_size)
{
/* Added the Host-Uniq. */
_nx_pppoe_server_tag_string_add(work_ptr, NX_PPPOE_SERVER_TAG_TYPE_RELAY_SESSION_ID, client_session_ptr -> nx_pppoe_relay_session_id_size, client_session_ptr -> nx_pppoe_relay_session_id, &index);
}
}
#ifdef NX_PPPOE_SERVER_SESSION_CONTROL_ENABLE
else if (code == NX_PPPOE_SERVER_CODE_PADT)
{
/* Check the Generic-Error. */
if (client_session_ptr -> nx_pppoe_generic_error)
{
/* Calculate the Generic-Error string length. */
if (_nx_utility_string_length_check((char *)(client_session_ptr -> nx_pppoe_generic_error), &tag_length, NX_MAX_STRING_LENGTH))
{
nx_packet_release(packet_ptr);
return(NX_SIZE_ERROR);
}
/* Added the Generic-Error. */
_nx_pppoe_server_tag_string_add(work_ptr, NX_PPPOE_SERVER_TAG_TYPE_GENERIC_ERROR, tag_length, client_session_ptr -> nx_pppoe_generic_error, &index);
}
}
#endif
/* Add the PPPoE header. */
/*
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* | VER | TYPE | CODE | SESSION_ID |
* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* | LENGTH | payload
* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*/
/* Add version and type. */
_nx_pppoe_server_data_add(work_ptr + NX_PPPOE_SERVER_OFFSET_VER_TYPE, 1, NX_PPPOE_SERVER_VERSION_TYPE);
/* Add code. */
_nx_pppoe_server_data_add(work_ptr + NX_PPPOE_SERVER_OFFSET_CODE, 1, code);
/* Add the Session id. */
if (code == NX_PPPOE_SERVER_CODE_PADO)
{
/* Add session id. */
_nx_pppoe_server_data_add(work_ptr + NX_PPPOE_SERVER_OFFSET_SESSION_ID, 2, 0);
}
else
{
/* Add session id. */
_nx_pppoe_server_data_add(work_ptr + NX_PPPOE_SERVER_OFFSET_SESSION_ID, 2, client_session_ptr -> nx_pppoe_session_id);
}
/* Add length. */
_nx_pppoe_server_data_add(work_ptr + NX_PPPOE_SERVER_OFFSET_LENGTH, 2, (index - NX_PPPOE_SERVER_OFFSET_PAYLOAD));
/* Update the append pointer and length. */
packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + index;
packet_ptr -> nx_packet_length = index;
/* Send PPPoE session packet. */
_nx_pppoe_server_packet_send(pppoe_server_ptr, client_session_ptr, packet_ptr, NX_LINK_PPPOE_DISCOVERY_SEND);
/* Return success. */
return(NX_PPPOE_SERVER_SUCCESS);
}
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _nx_pppoe_server_packet_send PORTABLE C */
/* 6.1 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function sends a PPPoE packet to the appropriate link driver. */
/* */
/* INPUT */
/* */
/* pppoe_server_ptr Pointer to PPPoE control block*/
/* client_session_ptr Pointer to Client Session */
/* packet_ptr Pointer to packet to send */
/* command Driver command */
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* (ip_link_driver) User supplied link driver */
/* */
/* CALLED BY */
/* */
/* _nx_pppoe_server_discovery_send Send PPPoE Discovery packet */
/* _nx_pppoe_server_session_send Send PPPoE Session packet */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
/* */
/**************************************************************************/
static VOID _nx_pppoe_server_packet_send(NX_PPPOE_SERVER *pppoe_server_ptr, NX_PPPOE_CLIENT_SESSION *client_session_ptr, NX_PACKET *packet_ptr, UINT command)
{
NX_IP_DRIVER driver_request;
/* Initialize the driver request. */
driver_request.nx_ip_driver_ptr = pppoe_server_ptr -> nx_pppoe_ip_ptr;
driver_request.nx_ip_driver_packet = packet_ptr;
driver_request.nx_ip_driver_interface = pppoe_server_ptr -> nx_pppoe_interface_ptr;
driver_request.nx_ip_driver_physical_address_msw = client_session_ptr -> nx_pppoe_physical_address_msw;
driver_request.nx_ip_driver_physical_address_lsw = client_session_ptr -> nx_pppoe_physical_address_lsw;
driver_request.nx_ip_driver_command = command;
/* Sendout the PPPoE packet. */
(pppoe_server_ptr -> nx_pppoe_link_driver_entry) (&driver_request);
}
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _nx_pppoe_server_tag_process PORTABLE C */
/* 6.1.4 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function processes tags of PPPoE packet. */
/* */
/* INPUT */
/* */
/* pppoe_server_ptr Pointer to PPPoE control block*/
/* client_session_ptr Pointer to Client Session */
/* code PPPoE code */
/* tag_ptr Pointer to PPPoE tag */
/* length Length of PPPoe tags */
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* _nx_pppoe_server_data_get Get the PPPoE data */
/* */
/* CALLED BY */
/* */
/* _nx_pppoe_server_discovery_packet_process */
/* Process PPPoE Discovery packet*/
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), improved */
/* packet length verification, */
/* verified memcpy use cases, */
/* resulting in version 6.1 */
/* 02-02-2021 Yuxin Zhou Modified comment(s), improved */
/* string length verification, */
/* fixed the compiler errors, */
/* resulting in version 6.1.4 */
/* */
/**************************************************************************/
static UINT _nx_pppoe_server_tag_process(NX_PPPOE_SERVER *pppoe_server_ptr, NX_PPPOE_CLIENT_SESSION *client_session_ptr, UINT code, UCHAR *tag_ptr, ULONG length)
{
ULONG tag_type;
ULONG tag_length;
UINT tag_index = 0;
UINT tag_service_name_count = 0;
UINT tag_service_name_valid = NX_FALSE;
UINT service_name_index = 0;
UINT service_name_length;
#ifdef NX_PPPOE_SERVER_SESSION_CONTROL_ENABLE
UCHAR *service_name_ptr;
#endif
/* Initialize the value. */
client_session_ptr -> nx_pppoe_host_uniq_size = 0;
client_session_ptr -> nx_pppoe_relay_session_id_size = 0;
client_session_ptr -> nx_pppoe_error_flag = 0;
#ifndef NX_PPPOE_SERVER_SESSION_CONTROL_ENABLE
client_session_ptr -> nx_pppoe_service_name = NX_NULL;
#endif
/* Loop to process the tag. */
while (tag_index + 4 <= length)
{
/* Pickup the tag type. */
tag_type = _nx_pppoe_server_data_get(tag_ptr + tag_index, 2);
/* Update the index. */
tag_index += 2;
/* Pickup the tag length. */
tag_length = _nx_pppoe_server_data_get(tag_ptr + tag_index, 2);
/* Update the index. */
tag_index += 2;
/* Check for valid tag length. */
if ((tag_index + tag_length) > length)
{
return(NX_PPPOE_SERVER_PACKET_PAYLOAD_ERROR);
}
/* Process the option type. */
switch (tag_type)
{
case NX_PPPOE_SERVER_TAG_TYPE_END_OF_LIST:
{
/* End tag. */
break;
}
case NX_PPPOE_SERVER_TAG_TYPE_SERVICE_NAME:
{
/* Service name tag. */
tag_service_name_count ++;
#ifdef NX_PPPOE_SERVER_SESSION_CONTROL_ENABLE
if (code == NX_PPPOE_SERVER_CODE_PADI)
{
/* The service name of incoming PADI must match the default service name of PPPoE. */
/* Check the tag length. */
if (tag_length == 0)
{
/* Check the default service name. */
if (pppoe_server_ptr -> nx_pppoe_service_name_count == 0)
tag_service_name_valid = NX_TRUE;
}
else
{
/* Loop to find the service name. */
while (service_name_index < pppoe_server_ptr -> nx_pppoe_service_name_count)
{
/* Get the length of service name. */
if (_nx_utility_string_length_check((char *)(pppoe_server_ptr -> nx_pppoe_service_name[service_name_index]),
&service_name_length, tag_length))
{
service_name_index++;
continue;
}
/* Compare the same service name with PPPoE Service Name. */
if ((service_name_length == tag_length) &&
(!memcmp(tag_ptr + tag_index, (pppoe_server_ptr -> nx_pppoe_service_name[service_name_index]), tag_length)))
{
tag_service_name_valid = NX_TRUE;
client_session_ptr -> nx_pppoe_service_name = pppoe_server_ptr -> nx_pppoe_service_name[service_name_index];
client_session_ptr -> nx_pppoe_service_name_length = service_name_length;
break;
}
service_name_index ++;
}
}
}
else if (code == NX_PPPOE_SERVER_CODE_PADR)
{
/* Compare the service name with session service name. */
/* Check the tag length. */
if ((tag_length == 0) && (client_session_ptr -> nx_pppoe_service_name_length == 0))
{
/* Update the information. */
tag_service_name_valid = NX_TRUE;
client_session_ptr -> nx_pppoe_service_name = NX_NULL;
client_session_ptr -> nx_pppoe_service_name_length = 0;
break;
}
/* Set the service name pointer. */
service_name_ptr = client_session_ptr -> nx_pppoe_service_name;
/* Loop to compare the service name with session service name. */
while(service_name_index < client_session_ptr -> nx_pppoe_service_name_length)
{
/* Get the service name. */
if (_nx_utility_string_length_check((char *)(service_name_ptr), &service_name_length, NX_MAX_STRING_LENGTH))
{
return(NX_PPPOE_SERVER_SERVICE_NAME_ERROR);
}
/* Check the tag length. */
if ((tag_length == 0) && (service_name_length == 0))
{
tag_service_name_valid = NX_TRUE;
}
else if ((tag_length != 0) && (tag_length == service_name_length))
{
/* Compare the service name. */
if (!memcmp(tag_ptr + tag_index, service_name_ptr, tag_length))
tag_service_name_valid = NX_TRUE;
}
/* Update the service name information for PADS. */
if (tag_service_name_valid == NX_TRUE)
{
client_session_ptr -> nx_pppoe_service_name = service_name_ptr;
client_session_ptr -> nx_pppoe_service_name_length = service_name_length;
break;
}
/* Update the service name pointer, length + null-terminated. */
service_name_ptr += (service_name_length + 1);
service_name_index += (service_name_length + 1);
}
}
#else
/* Check the tag length. */
if (tag_length == 0)
{
/* When the tag length is zero this tag is used to indicate that any service is acceptable. */
tag_service_name_valid = NX_TRUE;
break;
}
/* Compare the service name with PPPoE Service name. */
while (service_name_index < pppoe_server_ptr -> nx_pppoe_service_name_count)
{
/* Get the length of service name. */
if (_nx_utility_string_length_check((char *)(pppoe_server_ptr -> nx_pppoe_service_name[service_name_index]),
&service_name_length, tag_length))
{
service_name_index++;
continue;
}
/* Find the same service name. */
if ((service_name_length == tag_length) &&
(!memcmp(tag_ptr + tag_index, (pppoe_server_ptr -> nx_pppoe_service_name[service_name_index]), tag_length)))
{
/* Update the information. */
tag_service_name_valid = NX_TRUE;
client_session_ptr -> nx_pppoe_service_name = pppoe_server_ptr -> nx_pppoe_service_name[service_name_index];
break;
}
service_name_index ++;
}
#endif
break;
}
case NX_PPPOE_SERVER_TAG_TYPE_AC_NAME:
{
if (pppoe_server_ptr -> nx_pppoe_ac_name)
{
/* Check the access concentrator name. */
if ((pppoe_server_ptr -> nx_pppoe_ac_name_length != tag_length) ||
(memcmp(tag_ptr + tag_index, (pppoe_server_ptr -> nx_pppoe_ac_name), tag_length)))
{
return(NX_PPPOE_SERVER_AC_NAME_ERROR);
}
}
else
{
/* If user does not separately set Access Concentrator name, will use PPPoE server name as Access Concentrator name.*/
if ((pppoe_server_ptr -> nx_pppoe_name_length != tag_length) ||
(memcmp(tag_ptr + tag_index, (pppoe_server_ptr -> nx_pppoe_name), tag_length)))
{
return(NX_PPPOE_SERVER_AC_NAME_ERROR);
}
}
break;
}
case NX_PPPOE_SERVER_TAG_TYPE_HOST_UNIQ:
{
/* Check the cache for Host-Uniq. */
if (tag_length> NX_PPPOE_SERVER_MAX_HOST_UNIQ_SIZE)
return (NX_PPPOE_SERVER_HOST_UNIQ_CACHE_ERROR);
/* Save the Host-Uniq. */
memcpy(client_session_ptr -> nx_pppoe_host_uniq, tag_ptr + tag_index, tag_length); /* Use case of memcpy is verified. */
/* Set the Host-Uniq size. */
client_session_ptr -> nx_pppoe_host_uniq_size = tag_length;
break;
}
case NX_PPPOE_SERVER_TAG_TYPE_RELAY_SESSION_ID:
{
/* Check the cache for Relay-Session_Id. */
if (tag_length> NX_PPPOE_SERVER_MAX_RELAY_SESSION_ID_SIZE)
return (NX_PPPOE_SERVER_RELAY_SESSION_ID_CACHE_ERROR);
/* Save the Relay-Session_Id. */
memcpy(client_session_ptr -> nx_pppoe_relay_session_id, tag_ptr + tag_index, tag_length); /* Use case of memcpy is verified. */
/* Set the Relay-Session_Id size. */
client_session_ptr -> nx_pppoe_relay_session_id_size = tag_length;
break;
}
default:
break;
}
/* Move to the next tag. */
tag_index += tag_length;
}
/* Check the code. */
if ((code == NX_PPPOE_SERVER_CODE_PADI) || (code == NX_PPPOE_SERVER_CODE_PADR))
{
/* The PADI and PADR packet MUST contains exactly one TAG of TAG_TYPE Service- Name, RFC2516 */
if ((tag_service_name_count != 1) || (tag_service_name_valid != NX_TRUE))
{
/* Set the service name error flag. */
client_session_ptr -> nx_pppoe_error_flag |= NX_PPPOE_SERVER_ERROR_SERVICE_NAME;
/* Service-Name tag error. */
return(NX_PPPOE_SERVER_SERVICE_NAME_ERROR);
}
}
/* TAGs processed. */
return(NX_PPPOE_SERVER_SUCCESS);
}
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _nx_pppoe_server_data_get PORTABLE C */
/* 6.1 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function gets the datas of PPPoE packet. */
/* */
/* INPUT */
/* */
/* data Pointer to buffer data */
/* size Size of data value */
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* None */
/* */
/* CALLED BY */
/* */
/* _nx_pppoe_server_packet_receive Receive the PPPoE packet */
/* _nx_pppoe_server_discovery_packet_process */
/* Process PPPoE Discovery packet*/
/* _nx_pppoe_server_session_packet_process */
/* Process PPPoE Session packet */
/* _nx_pppoe_server_tag_process Process PPPoE TAGs */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
/* */
/**************************************************************************/
static ULONG _nx_pppoe_server_data_get(UCHAR *data, UINT size)
{
ULONG value = 0;
/* Process the data retrieval request. */
while (size-- > 0)
{
/* Build return value. */
value = (value << 8) | *data++;
}
/* Return value. */
return(value);
}
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _nx_pppoe_server_data_add PORTABLE C */
/* 6.1 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function adds the datas into PPPoE packet. */
/* */
/* INPUT */
/* */
/* data Pointer to buffer data */
/* size Size of data value */
/* value Value to add */
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* None */
/* */
/* CALLED BY */
/* */
/* _nx_pppoe_server_discovery_send Send PPPoE Discovery packet */
/* _nx_pppoe_server_session_send Send PPPoE Session packet */
/* _nx_pppoe_server_tag_string_add Add PPPoE string TAG */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
/* */
/**************************************************************************/
static VOID _nx_pppoe_server_data_add(UCHAR *data, UINT size, ULONG value)
{
/* Make sure that data is left justified. */
switch (size)
{
case 1:
value <<= 24;
break;
case 2:
value <<= 16;
break;
case 3:
value <<= 8;
break;
default:
break;
}
/* Store the value. */
while (size-- > 0)
{
*data = (UCHAR) ((value >> 24) & 0xff);
data++;
value <<= 8;
}
}
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _nx_pppoe_server_string_add PORTABLE C */
/* 6.1 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function adds the string into PPPoE packet. */
/* */
/* INPUT */
/* */
/* dest Pointer to destination buffer */
/* source Pointer to source buffer */
/* size Number of bytes to add */
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* None */
/* */
/* CALLED BY */
/* */
/* _nx_pppoe_server_tag_string_add Add PPPoE string TAG */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
/* */
/**************************************************************************/
static VOID _nx_pppoe_server_string_add(UCHAR *dest, UCHAR *source, UINT size)
{
/* Loop to copy all bytes. */
while (size-- > 0)
{
/* Copy a byte. */
*dest++ = *source++;
}
}
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _nx_pppoe_server_tag_string_add PORTABLE C */
/* 6.1 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function adds the TAG with string into PPPoE packet. */
/* */
/* INPUT */
/* */
/* data_ptr Pointer to data buffer */
/* tag_type Type of TAG */
/* tag_length Length of TAG */
/* tag_value_string String value of TAG to add */
/* index Location into data buffer */
/* to write data */
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* _nx_pppoe_server_data_add Add PPPoE data */
/* _nx_pppoe_server_string_add Add PPPoE string data */
/* */
/* CALLED BY */
/* */
/* _nx_pppoe_server_discovery_send Send PPPoE Discovery packet */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
/* */
/**************************************************************************/
static UINT _nx_pppoe_server_tag_string_add(UCHAR *data_ptr, UINT tag_type, UINT tag_length, UCHAR *tag_value_string, UINT *index)
{
/* Add the tag type. */
_nx_pppoe_server_data_add(data_ptr + (*index), 2, tag_type);
(*index) += 2;
/* Add the tag length. */
_nx_pppoe_server_data_add(data_ptr + (*index), 2, tag_length);
(*index) += 2;
/* Add the tag value string. */
_nx_pppoe_server_string_add(data_ptr + (*index), tag_value_string, tag_length);
(*index) += tag_length;
/* Return a successful completion. */
return(NX_PPPOE_SERVER_SUCCESS);
}
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _nx_pppoe_server_session_find PORTABLE C */
/* 6.1 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function finds a PPPoE session by the client hardware mac */
/* address and session id. In Discovery Stage, match the client harware*/
/* address, if not match, mark one available session. In Session Stage,*/
/* match the client harware address and session id, if not match, */
/* return NX_PPPOE_CLIENT_SESSION_NOT_FOUND. */
/* */
/* INPUT */
/* */
/* pppoe_server_ptr Pointer to PPPoE control block*/
/* client_mac_msw Client physical address MSW */
/* client_mac_lsw Client physical address LSW */
/* session_id Session ID */
/* session_index Session Index */
/* client_session_ptr Pointer to Client Session */
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* None */
/* */
/* CALLED BY */
/* */
/* _nx_pppoe_server_discovery_packet_process */
/* Process PPPoE Discovery packet*/
/* _nx_pppoe_server_session_packet_process */
/* Process PPPoE Session packet */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
/* */
/**************************************************************************/
static UINT _nx_pppoe_server_session_find(NX_PPPOE_SERVER *pppoe_server_ptr, ULONG client_mac_msw, ULONG client_mac_lsw,
ULONG session_id, UINT *session_index, NX_PPPOE_CLIENT_SESSION **client_session_ptr)
{
UINT i;
UINT available_index;
/* Initialize the value. */
i = 0;
available_index = NX_PPPOE_SERVER_MAX_CLIENT_SESSION_NUMBER;
for(i = 0; i < NX_PPPOE_SERVER_MAX_CLIENT_SESSION_NUMBER; i ++)
{
/* Check if this session is valid. */
if (pppoe_server_ptr -> nx_pppoe_client_session[i].nx_pppoe_valid == NX_TRUE)
{
/* Compare the physical address. */
if ((pppoe_server_ptr -> nx_pppoe_client_session[i].nx_pppoe_physical_address_msw != client_mac_msw) ||
(pppoe_server_ptr -> nx_pppoe_client_session[i].nx_pppoe_physical_address_lsw != client_mac_lsw))
continue;
/* If the session id is not zero, means the session has been established. */
if (session_id != 0)
{
/* Compare the session id. */
if (pppoe_server_ptr -> nx_pppoe_client_session[i].nx_pppoe_session_id != session_id)
continue;
}
/* Yes, find the matched session. */
*session_index = i;
*client_session_ptr = &(pppoe_server_ptr -> nx_pppoe_client_session[i]);
return(NX_PPPOE_SERVER_SUCCESS);
}
else
{
/* Set the first available index. */
if (i < available_index)
available_index = i;
}
}
/* If the session id is not zero, means the session has been established. */
if (session_id != 0)
{
return(NX_PPPOE_SERVER_CLIENT_SESSION_NOT_FOUND);
}
/* Check if there is available room in the table for a new client session. */
if (available_index >= NX_PPPOE_SERVER_MAX_CLIENT_SESSION_NUMBER)
{
/* No, we cannot add this client session into the server's table. */
return(NX_PPPOE_SERVER_CLIENT_SESSION_FULL);
}
/* Set the session. */
pppoe_server_ptr -> nx_pppoe_client_session[available_index].nx_pppoe_physical_address_msw = client_mac_msw;
pppoe_server_ptr -> nx_pppoe_client_session[available_index].nx_pppoe_physical_address_lsw = client_mac_lsw;
/* Mark this session is valid. */
pppoe_server_ptr -> nx_pppoe_client_session[available_index].nx_pppoe_valid = NX_TRUE;
/* Set local pointer to an available slot. */
*session_index = available_index;
*client_session_ptr = &(pppoe_server_ptr -> nx_pppoe_client_session[available_index]);
/* Return success. */
return(NX_PPPOE_SERVER_SUCCESS);
}
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _nx_pppoe_server_session_cleanup PORTABLE C */
/* 6.1 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function cleans up the PPPoE session. */
/* */
/* INPUT */
/* */
/* client_session_ptr Pointer to Client Session */
/* */
/* OUTPUT */
/* */
/* status Completion status */
/* */
/* CALLS */
/* */
/* None */
/* */
/* CALLED BY */
/* */
/* _nx_pppoe_server_session_terminate Terminate the PPPoE session */
/* _nx_pppoe_server_session_packet_process */
/* Process PPPoE Session packet */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
/* */
/**************************************************************************/
static UINT _nx_pppoe_server_session_cleanup(NX_PPPOE_CLIENT_SESSION *client_session_ptr)
{
#ifdef NX_PPPOE_SERVER_SESSION_CONTROL_ENABLE
NX_PACKET *next_packet;
NX_PACKET *current_packet;
#endif
/* Cleanup the client session. */
client_session_ptr -> nx_pppoe_valid = NX_FALSE;
client_session_ptr -> nx_pppoe_session_id = NX_NULL;
client_session_ptr -> nx_pppoe_physical_address_msw = NX_NULL;
client_session_ptr -> nx_pppoe_physical_address_lsw = NX_NULL;
client_session_ptr -> nx_pppoe_service_name = NX_NULL;
#ifdef NX_PPPOE_SERVER_SESSION_CONTROL_ENABLE
/* Loop to release the queued packet. */
next_packet = client_session_ptr -> nx_pppoe_deferred_received_packet_head;
/* Release any packets queued up. */
while (next_packet)
{
/* Setup the current packet pointer. */
current_packet = next_packet;
/* Move to the next packet. */
next_packet = next_packet -> nx_packet_queue_next;
/* Release the current packet. */
nx_packet_release(current_packet);
}
/* Cleanup the parameters. */
client_session_ptr -> nx_pppoe_deferred_received_packet_head = NX_NULL;
client_session_ptr -> nx_pppoe_deferred_received_packet_tail = NX_NULL;
client_session_ptr -> nx_pppoe_packet_receive_stopped = NX_FALSE;
#endif
/* Return success. */
return(NX_PPPOE_SERVER_SUCCESS);
}
#ifdef NX_PPPOE_SERVER_SESSION_CONTROL_ENABLE
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* PppInitInd PORTABLE C */
/* 6.1.4 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function configures the default Service Namet that the PPPoE */
/* should use to filter incoming PADI requests. */
/* */
/* INPUT */
/* */
/* length The number of bytes in aData */
/* aData Contains PPPoE Service Name */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* _nx_pppoe_server_service_name_set Set the service name */
/* */
/* CALLED BY */
/* */
/* Application */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
/* 02-02-2021 Yuxin Zhou Modified comment(s), */
/* fixed the compiler errors, */
/* resulting in version 6.1.4 */
/* */
/**************************************************************************/
VOID PppInitInd(UINT length, UCHAR *aData)
{
/* Check to see if PPPoE instance is created. */
if ((_nx_pppoe_server_created_ptr == NX_NULL) ||
(_nx_pppoe_server_created_ptr -> nx_pppoe_id != NX_PPPOE_SERVER_ID))
return;
/* Check the length. */
if (length == 0)
{
/* Clean the default service name. */
_nx_pppoe_server_service_name_set(_nx_pppoe_server_created_ptr, NX_NULL, 0);
}
else
{
/* Transmit the Service. */
nx_pppoe_service_name[0] = aData;
/* Set the default service name. */
_nx_pppoe_server_service_name_set(_nx_pppoe_server_created_ptr, nx_pppoe_service_name, 1);
}
}
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* PppDiscoverCnf PORTABLE C */
/* 6.1 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function defines the Service Name field of the PADO packet. */
/* */
/* INPUT */
/* */
/* interfaceHandle The handle of session */
/* length The number of bytes in aData */
/* aData Contains PPPoE Service Name */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* tx_mutex_get Obtain a protection mutex */
/* tx_mutex_put Release protection mutex */
/* _nx_pppoe_server_discovery_send Send PPPoE Discovery */
/* */
/* CALLED BY */
/* */
/* Application */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
/* */
/**************************************************************************/
VOID PppDiscoverCnf(UINT length, UCHAR *aData, UINT interfaceHandle)
{
NX_PPPOE_CLIENT_SESSION *client_session_ptr;
/* Check to see if PPPoE instance is created. */
if ((_nx_pppoe_server_created_ptr == NX_NULL) ||
(_nx_pppoe_server_created_ptr -> nx_pppoe_id != NX_PPPOE_SERVER_ID))
return;
/* Check to see if PPPoE is enabled. */
if (_nx_pppoe_server_created_ptr -> nx_pppoe_enabled != NX_TRUE)
return;
/* Check for invalid session index. */
if(interfaceHandle >= NX_PPPOE_SERVER_MAX_CLIENT_SESSION_NUMBER)
return;
/* Check to see if PPPoE session is valid. */
if (_nx_pppoe_server_created_ptr -> nx_pppoe_client_session[interfaceHandle].nx_pppoe_valid != NX_TRUE)
return;
/* Obtain the IP internal mutex before processing the IP event. */
tx_mutex_get(&(_nx_pppoe_server_created_ptr -> nx_pppoe_ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
/* Get the Session pointer. */
client_session_ptr = &(_nx_pppoe_server_created_ptr -> nx_pppoe_client_session[interfaceHandle]);
/* Check if this session is valid. */
if (client_session_ptr -> nx_pppoe_valid != NX_TRUE)
{
/* Release the IP internal mutex. */
tx_mutex_put(&(_nx_pppoe_server_created_ptr -> nx_pppoe_ip_ptr -> nx_ip_protection));
return;
}
/* Set the Service Name field. */
client_session_ptr -> nx_pppoe_service_name = aData;
client_session_ptr -> nx_pppoe_service_name_length = length;
/* Send PADO packet. */
_nx_pppoe_server_discovery_send(_nx_pppoe_server_created_ptr, client_session_ptr, NX_PPPOE_SERVER_CODE_PADO);
/* Release the IP internal mutex. */
tx_mutex_put(&(_nx_pppoe_server_created_ptr -> nx_pppoe_ip_ptr -> nx_ip_protection));
return;
}
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* PppOpenCnf PORTABLE C */
/* 6.1 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function allows PPPoE to accept or reject the PPPoE Session. */
/* */
/* INPUT */
/* */
/* accept The flag to accept or reject */
/* interfaceHandle The handle of session */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* tx_mutex_get Obtain a protection mutex */
/* tx_mutex_put Release protection mutex */
/* _nx_pppoe_server_discovery_send Send PPPoE Discovery */
/* _nx_pppoe_server_session_cleanup Cleanup the PPPoE Session */
/* */
/* CALLED BY */
/* */
/* Application */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
/* */
/**************************************************************************/
VOID PppOpenCnf(UCHAR accept, UINT interfaceHandle)
{
NX_PPPOE_CLIENT_SESSION *client_session_ptr;
/* Check to see if PPPoE instance is created. */
if ((_nx_pppoe_server_created_ptr == NX_NULL) ||
(_nx_pppoe_server_created_ptr -> nx_pppoe_id != NX_PPPOE_SERVER_ID))
return;
/* Check to see if PPPoE is enabled. */
if (_nx_pppoe_server_created_ptr -> nx_pppoe_enabled != NX_TRUE)
return;
/* Check for invalid session index. */
if(interfaceHandle >= NX_PPPOE_SERVER_MAX_CLIENT_SESSION_NUMBER)
return;
/* Check to see if PPPoE session is valid. */
if (_nx_pppoe_server_created_ptr -> nx_pppoe_client_session[interfaceHandle].nx_pppoe_valid != NX_TRUE)
return;
/* Obtain the IP internal mutex before processing the IP event. */
tx_mutex_get(&(_nx_pppoe_server_created_ptr -> nx_pppoe_ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
/* Get the Session pointer. */
client_session_ptr = &(_nx_pppoe_server_created_ptr -> nx_pppoe_client_session[interfaceHandle]);
/* Check the accept flag. */
if (accept == NX_TRUE)
{
/* Send PADS to accept the PPPoE Session. */
_nx_pppoe_server_discovery_send(_nx_pppoe_server_created_ptr, client_session_ptr, NX_PPPOE_SERVER_CODE_PADS);
}
else
{
/* Reject the PPPoE Session. */
_nx_pppoe_server_session_cleanup(client_session_ptr);
}
/* Release the IP internal mutex. */
tx_mutex_put(&(_nx_pppoe_server_created_ptr -> nx_pppoe_ip_ptr -> nx_ip_protection));
return;
}
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* PppCloseInd PORTABLE C */
/* 6.1.4 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function allows PPPoE to terminate PPPoE Session. */
/* */
/* INPUT */
/* */
/* interfaceHandle The handle of session */
/* causeCode The reason for terminating */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* _nx_pppoe_server_session_terminate Terminate the PPPoE Session */
/* */
/* CALLED BY */
/* */
/* Application */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
/* 02-02-2021 Yuxin Zhou Modified comment(s), */
/* fixed the compiler errors, */
/* resulting in version 6.1.4 */
/* */
/**************************************************************************/
VOID PppCloseInd(UINT interfaceHandle, UCHAR *causeCode)
{
/* Check to see if PPPoE instance is created. */
if ((_nx_pppoe_server_created_ptr == NX_NULL) ||
(_nx_pppoe_server_created_ptr -> nx_pppoe_id != NX_PPPOE_SERVER_ID))
return;
/* Check to see if PPPoE is enabled. */
if (_nx_pppoe_server_created_ptr -> nx_pppoe_enabled != NX_TRUE)
return;
/* Check for invalid session index. */
if(interfaceHandle >= NX_PPPOE_SERVER_MAX_CLIENT_SESSION_NUMBER)
return;
/* Check to see if PPPoE session is established. */
if ((_nx_pppoe_server_created_ptr -> nx_pppoe_client_session[interfaceHandle].nx_pppoe_valid != NX_TRUE) ||
(_nx_pppoe_server_created_ptr -> nx_pppoe_client_session[interfaceHandle].nx_pppoe_session_id == 0))
return;
/* Obtain the IP internal mutex before processing the IP event. */
tx_mutex_get(&(_nx_pppoe_server_created_ptr -> nx_pppoe_ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
/* Set the reason for terminating the session. */
_nx_pppoe_server_created_ptr -> nx_pppoe_client_session[interfaceHandle].nx_pppoe_generic_error = causeCode;
/* Send PADT to terminate the session. */
_nx_pppoe_server_session_terminate(_nx_pppoe_server_created_ptr, interfaceHandle);
/* Release the IP internal mutex. */
tx_mutex_put(&(_nx_pppoe_server_created_ptr -> nx_pppoe_ip_ptr -> nx_ip_protection));
return;
}
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* PppCloseCnf PORTABLE C */
/* 6.1 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function confirm that the session has been freed. */
/* */
/* INPUT */
/* */
/* interfaceHandle The handle of session */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* None */
/* */
/* CALLED BY */
/* */
/* Application */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
/* */
/**************************************************************************/
VOID PppCloseCnf(UINT interfaceHandle)
{
/* Check to see if PPPoE instance is created. */
if ((_nx_pppoe_server_created_ptr == NX_NULL) ||
(_nx_pppoe_server_created_ptr -> nx_pppoe_id != NX_PPPOE_SERVER_ID))
return;
/* Check for invalid session index. */
if (interfaceHandle >= NX_PPPOE_SERVER_MAX_CLIENT_SESSION_NUMBER)
return;
/* Obtain the IP internal mutex before processing the IP event. */
tx_mutex_get(&(_nx_pppoe_server_created_ptr -> nx_pppoe_ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
/* Cleanup the PPPoE session. */
_nx_pppoe_server_session_cleanup(&(_nx_pppoe_server_created_ptr -> nx_pppoe_client_session[interfaceHandle]));
/* Release the IP internal mutex. */
tx_mutex_put(&(_nx_pppoe_server_created_ptr -> nx_pppoe_ip_ptr -> nx_ip_protection));
}
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* PppTransmitDataCnf PORTABLE C */
/* 6.1.4 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function allows TTP's software to receive new data frame. */
/* */
/* INPUT */
/* */
/* interfaceHandle The handle of session */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* tx_mutex_get Obtain a protection mutex */
/* tx_mutex_put Release protection mutex */
/* tx_event_flags_set Set events for PPPoE thread */
/* */
/* CALLED BY */
/* */
/* Application */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
/* 02-02-2021 Yuxin Zhou Modified comment(s), */
/* fixed the compiler errors, */
/* resulting in version 6.1.4 */
/* */
/**************************************************************************/
VOID PppTransmitDataCnf(UINT interfaceHandle, UCHAR *data_ptr, UINT packet_id)
{
NX_PACKET *packet_ptr;
NX_PARAMETER_NOT_USED(data_ptr);
/* Check to see if PPPoE instance is created. */
if ((_nx_pppoe_server_created_ptr == NX_NULL) ||
(_nx_pppoe_server_created_ptr -> nx_pppoe_id != NX_PPPOE_SERVER_ID))
return;
/* Check for invalid session index. */
if(interfaceHandle >= NX_PPPOE_SERVER_MAX_CLIENT_SESSION_NUMBER)
return;
/* Obtain the IP internal mutex before processing the IP event. */
tx_mutex_get(&(_nx_pppoe_server_created_ptr -> nx_pppoe_ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
/* Release the packet. */
if (packet_id)
{
packet_ptr = (NX_PACKET *)(packet_id);
nx_packet_release(packet_ptr);
}
/* Clean the flag to receive the next packet. */
_nx_pppoe_server_created_ptr -> nx_pppoe_client_session[interfaceHandle].nx_pppoe_packet_receive_stopped = NX_FALSE;
/* Check if this session queued the packets. */
if (_nx_pppoe_server_created_ptr -> nx_pppoe_client_session[interfaceHandle].nx_pppoe_deferred_received_packet_head)
{
/* Wakeup PPPoE helper thread to process the PPPoE Session receive. */
tx_event_flags_set(&(_nx_pppoe_server_created_ptr -> nx_pppoe_events), NX_PPPOE_SERVER_SESSION_RECEIVE_EVENT, TX_OR);
}
/* Release the IP internal mutex. */
tx_mutex_put(&(_nx_pppoe_server_created_ptr -> nx_pppoe_ip_ptr -> nx_ip_protection));
}
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* PppReceiveDataInd PORTABLE C */
/* 6.1.4 */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function sends data fram over Ethernet. */
/* */
/* INPUT */
/* */
/* interfaceHandle The handle of session */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* _nx_pppoe_server_session_send Send PPPoE session data */
/* */
/* CALLED BY */
/* */
/* Application */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
/* resulting in version 6.1 */
/* 02-02-2021 Yuxin Zhou Modified comment(s), */
/* fixed the compiler errors, */
/* resulting in version 6.1.4 */
/* */
/**************************************************************************/
VOID PppReceiveDataInd(UINT interfaceHandle, UINT data_length, UCHAR *data_ptr)
{
/* Check for invalid input pointers. */
if ((_nx_pppoe_server_created_ptr == NX_NULL) ||
(_nx_pppoe_server_created_ptr -> nx_pppoe_id != NX_PPPOE_SERVER_ID))
return;
/* Check to see if PPPoE is enabled. */
if (_nx_pppoe_server_created_ptr -> nx_pppoe_enabled != NX_TRUE)
return;
/* Check for invalid session index. */
if(interfaceHandle >= NX_PPPOE_SERVER_MAX_CLIENT_SESSION_NUMBER)
return;
/* Check to see if PPPoE session is established. */
if ((_nx_pppoe_server_created_ptr -> nx_pppoe_client_session[interfaceHandle].nx_pppoe_valid != NX_TRUE) ||
(_nx_pppoe_server_created_ptr -> nx_pppoe_client_session[interfaceHandle].nx_pppoe_session_id == 0))
return;
/* Send data. */
_nx_pppoe_server_session_send(_nx_pppoe_server_created_ptr, interfaceHandle, data_ptr, data_length);
}
#endif