AzureMXChip/MXCHIPAZ3166/core/lib/netxduo/addons/dhcp/nxd_dhcpv6_server.c
UINT _nx_dhcpv6_add_client_record(NX_DHCPV6_SERVER *dhcpv6_server_ptr, UINT table_index, ULONG message_xid, NXD_ADDRESS *client_address, UINT client_state, 
                                  ULONG IP_lease_time_accrued, ULONG valid_lifetime, UINT duid_type,  UINT duid_hardware, ULONG physical_address_msw, 
                                  ULONG physical_address_lsw, ULONG duid_time, ULONG duid_vendor_number, UCHAR *duid_vendor_private, UINT duid_private_length)
{

UINT i;
UINT found = NX_FALSE;
NX_DHCPV6_CLIENT *dhcpv6_client_ptr; 


    /* Check if a table index was specified. */
    if (table_index != 0xFFFFFFFF)
    {

        /* Check if it is a valid index. */
        if (table_index >= NX_DHCPV6_MAX_CLIENTS)
        {
        
            /* No, return a parameter error. */
            return NX_INVALID_PARAMETERS;
        }

        /* Check if it is actually empty. */
        if (dhcpv6_server_ptr -> nx_dhcpv6_clients[table_index].nx_dhcpv6_message_xid != 0)
        {

            /* Not empty. Indicate we'll have to find an empty slot. */
            table_index = 0xFFFFFFFF;
        }
    }

    /* Check if we still need to find a slot. */
    if (table_index == 0xFFFFFFFF)
    {

        /* We do, so loop through client records to find one. */
        for (i = 0; i < NX_DHCPV6_MAX_CLIENTS; i++)
        {

            /* Is this an empty slot? */
            if (dhcpv6_server_ptr -> nx_dhcpv6_clients[i].nx_dhcpv6_message_xid == 0)
            {

                /* This is available. */
                table_index = i;
                break;
            }
        }

        /* Do we have a slot?  */
        if (i == NX_DHCPV6_MAX_CLIENTS)
        {

            /* No, Indicate the table is full. */
            return NX_DHCPV6_TABLE_FULL;
        }
    }

    /* Create the table entry. */

    /* Fill in the generic client information. */
    dhcpv6_client_ptr =  &(dhcpv6_server_ptr -> nx_dhcpv6_clients[table_index]);
    dhcpv6_client_ptr -> nx_dhcpv6_id = NX_DHCPV6_CLIENT_ID;
    dhcpv6_client_ptr -> nx_dhcpv6_message_xid = message_xid;
    dhcpv6_client_ptr -> nx_dhcpv6_state = (UCHAR)client_state;
    dhcpv6_client_ptr -> nx_dhcpv6_IP_lease_time_accrued  = IP_lease_time_accrued;
    memcpy(&(dhcpv6_client_ptr -> nx_dhcpv6_server_duid), &(dhcpv6_server_ptr -> nx_dhcpv6_server_duid), sizeof(NX_DHCPV6_SVR_DUID)); /* Use case of memcpy is verified. */

    /*Fill in the Client DUID information. */
    dhcpv6_client_ptr -> nx_dhcpv6_client_duid.nx_op_code = NX_DHCPV6_OP_DUID_CLIENT;
    dhcpv6_client_ptr -> nx_dhcpv6_client_duid.nx_hardware_type = (USHORT)duid_hardware;
    dhcpv6_client_ptr -> nx_dhcpv6_client_duid.nx_duid_type = (USHORT)duid_type;

    /* Determine DUID type to fill in the rest of the DUID fields. */
    if (duid_type == NX_DHCPV6_SERVER_DUID_TYPE_VENDOR_ASSIGNED)
    {

        /* Validate the DUID private length. */
        if (duid_private_length > NX_DHCPV6_SERVER_DUID_VENDOR_ASSIGNED_LENGTH)
        {
            return NX_DHCPV6_INVALID_DUID;
        }

        dhcpv6_client_ptr -> nx_dhcpv6_client_duid.nx_duid_enterprise_number = duid_vendor_number;
        memcpy(&(dhcpv6_client_ptr -> nx_dhcpv6_client_duid.nx_duid_private_identifier[0]), duid_vendor_private, duid_private_length); /* Use case of memcpy is verified. */
        dhcpv6_client_ptr -> nx_dhcpv6_client_duid.nx_option_length = (USHORT)(duid_private_length + 6);
    }
    else 
    {

        /* Either link layer or link layer plus time. */
        dhcpv6_client_ptr -> nx_dhcpv6_client_duid.nx_link_layer_address_msw = (USHORT)physical_address_msw;
        dhcpv6_client_ptr -> nx_dhcpv6_client_duid.nx_link_layer_address_lsw = physical_address_lsw;
        dhcpv6_client_ptr -> nx_dhcpv6_client_duid.nx_option_length = 10;

        if (duid_type == NX_DHCPV6_SERVER_DUID_TYPE_LINK_TIME)
        {
        
            dhcpv6_client_ptr -> nx_dhcpv6_client_duid.nx_option_length = 14;
            dhcpv6_client_ptr -> nx_dhcpv6_client_duid.nx_duid_time = duid_time;
        }
    }

    /* Fill in the necessary IA-NA and IA Address option fields. */
    dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_op_code = NX_DHCPV6_OP_IA_ADDRESS;
    dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_option_length = 24;
    dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_valid_lifetime = valid_lifetime;
    dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_preferred_lifetime = 0; /* Don't care */
    COPY_NXD_ADDRESS(client_address, &(dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_global_address));

    dhcpv6_client_ptr -> nx_dhcpv6_iana_status.nx_op_code = NX_DHCPV6_OP_OPTION_STATUS;
    dhcpv6_client_ptr -> nx_dhcpv6_iana_status.nx_option_length = 2; /* No message */
    dhcpv6_client_ptr -> nx_dhcpv6_iana_status.nx_status_code = NX_DHCPV6_STATUS_SUCCESS;

    /* Now access the server lease table to find this client's lease. */
    for (i = 0; i < NX_DHCPV6_MAX_LEASES; i++)
    {

        /* Compare our client's assigned IP address with this lease table entry. */
        if(CHECK_IPV6_ADDRESSES_SAME(&(client_address -> nxd_ip_address.v6[0]), 
                                     &(dhcpv6_server_ptr -> nx_dhcpv6_lease_list[i].nx_dhcpv6_lease_IP_address.nxd_ip_address.v6[0])))
        {

            /* They match! Cross link the tables. */
            dhcpv6_server_ptr -> nx_dhcpv6_lease_list[i].nx_dhcpv6_lease_assigned_to = dhcpv6_client_ptr;
            found = NX_TRUE;
            break;
        }
    }

    if (!found)
    {

        /* This client apparently does not have a valid IP lease. Ok to keep in the tables,
           but they will need to request an IP address! */
        return NX_DHCPV6_ADDRESS_NOT_FOUND;
    }

    return NX_SUCCESS;

}
/**************************************************************************/
/*                                                                        */
/*  FUNCTION                                               RELEASE        */
/*                                                                        */
/*    _nx_dhcpv6_add_client_record                        PORTABLE C      */
/*                                                           6.1          */
/*  AUTHOR                                                                */
/*                                                                        */
/*    Yuxin Zhou, Microsoft Corporation                                   */
/*                                                                        */
/*  DESCRIPTION                                                           */
/*                                                                        */
/*   This function copies the input data into a DHCPv6 Client record and  */
/*   stored in the server's Client table.  It then uses the Client IP     */
/*   address to find the matching record in the server IP lease table to  */
/*   cross link the tables.                                               */
/*                                                                        */
/*   This is intended to satisfy the DHCPv6 protocol requirement that a   */
/*   DHPCv6 Server be able to store and retrieve lease data from          */
/*   nonvolatile memory e..g between reboots.                             */
/*                                                                        */
/*  INPUT                                                                 */
/*                                                                        */
/*    dhcpv6_server_ptr                  Pointer to DHCPv6 server         */
/*    table_index                        Table index to store client data */
/*    message_xid                        Client transaction ID            */
/*    client_address                     IP address leased to client      */
/*    client_state                       Client DHCPv6 state e.g. bound   */
/*    IP_lease_time_accrued              Time expired on current IP lease */
/*    valid_lifetime                     When address becomes invalid     */
/*    duid_type                          Type of Client DUID              */
/*    duid_hardware                      DUID hardware (usually ethernet) */
/*    physical_address_msw               MSB of client mac address        */
/*    physical_address_lsw               LSB of client mac address        */
/*    duid_time                          Time for link layer time DUID    */
/*    duid_vendor_number                 Enterprise ID for Vendor DUID    */
/*    duid_vendor_private                Pointer to private ID for DUID   */
/*    duid_private_length                Vendor Duid private ID length    */
/*                                                                        */
/*  OUTPUT                                                                */
/*                                                                        */
/*    NX_SUCCESS                         Successful IP address copy       */
/*    NX_DHCPV6_PARAM_ERROR              Invalid non pointer input        */
/*    NX_DHCPV6_TABLE_FULL               No empty slot for client data    */
/*                                                                        */
/*  CALLS                                                                 */
/*                                                                        */
/*    memcpy                             Copy data to specified memory    */
/*                                                                        */
/*  CALLED BY                                                             */
/*                                                                        */
/*    Application code                                                    */
/*                                                                        */
/*  RELEASE HISTORY                                                       */
/*                                                                        */
/*    DATE              NAME                      DESCRIPTION             */
/*                                                                        */
/*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
/*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
/*                                            verified memcpy use cases,  */
/*                                            resulting in version 6.1    */
/*                                                                        */
/**************************************************************************/
FUNCTION                                               RELEASE

_nx_dhcpv6_add_client_record                        PORTABLE C
6.1
AUTHOR

Yuxin Zhou, Microsoft Corporation

DESCRIPTION

This function copies the input data into a DHCPv6 Client record and
stored in the server's Client table.  It then uses the Client IP
address to find the matching record in the server IP lease table to
cross link the tables.

This is intended to satisfy the DHCPv6 protocol requirement that a
DHPCv6 Server be able to store and retrieve lease data from
nonvolatile memory e..g between reboots.

INPUT

dhcpv6_server_ptr                  Pointer to DHCPv6 server
table_index                        Table index to store client data
message_xid                        Client transaction ID
client_address                     IP address leased to client
client_state                       Client DHCPv6 state e.g. bound
IP_lease_time_accrued              Time expired on current IP lease
valid_lifetime                     When address becomes invalid
duid_type                          Type of Client DUID
duid_hardware                      DUID hardware (usually ethernet)
physical_address_msw               MSB of client mac address
physical_address_lsw               LSB of client mac address
duid_time                          Time for link layer time DUID
duid_vendor_number                 Enterprise ID for Vendor DUID
duid_vendor_private                Pointer to private ID for DUID
duid_private_length                Vendor Duid private ID length

OUTPUT

NX_SUCCESS                         Successful IP address copy
NX_DHCPV6_PARAM_ERROR              Invalid non pointer input
NX_DHCPV6_TABLE_FULL               No empty slot for client data

CALLS

memcpy                             Copy data to specified memory

CALLED BY

Application code

RELEASE HISTORY

DATE              NAME                      DESCRIPTION

05-19-2020     Yuxin Zhou               Initial Version 6.0
09-30-2020     Yuxin Zhou               Modified comment(s), and
verified memcpy use cases,
resulting in version 6.1
FUNCTION RELEASE _nx_dhcpv6_add_client_record PORTABLE C 6 . 1 AUTHOR Yuxin Zhou Microsoft Corporation DESCRIPTION This function copies the input data into a DHCPv6 Client record and stored in the server ' s Client table . It then uses the Client IP address to find the matching record in the server IP lease table to cross link the tables . This is intended to satisfy the DHCPv6 protocol requirement that a DHPCv6 Server be able to store and retrieve lease data from nonvolatile memory e .. g between reboots . INPUT dhcpv6_server_ptr Pointer to DHCPv6 server table_index Table index to store client data message_xid Client transaction ID client_address IP address leased to client client_state Client DHCPv6 state e . g . bound IP_lease_time_accrued Time expired on current IP lease valid_lifetime When address becomes invalid duid_type Type of Client DUID duid_hardware DUID hardware ( usually ethernet ) physical_address_msw MSB of client mac address physical_address_lsw LSB of client mac address duid_time Time for link layer time DUID duid_vendor_number Enterprise ID for Vendor DUID duid_vendor_private Pointer to private ID for DUID duid_private_length Vendor Duid private ID length OUTPUT NX_SUCCESS Successful IP address copy NX_DHCPV6_PARAM_ERROR Invalid non pointer input NX_DHCPV6_TABLE_FULL No empty slot for client data CALLS memcpy Copy data to specified memory CALLED BY Application code RELEASE HISTORY DATE NAME DESCRIPTION 05 - 19 - 2020 Yuxin Zhou Initial Version 6 . 0 09 - 30 - 2020 Yuxin Zhou Modified comment ( s ) and verified memcpy use cases resulting in version 6 . 1
UINT _nx_dhcpv6_add_client_record(NX_DHCPV6_SERVER *dhcpv6_server_ptr, UINT table_index, ULONG message_xid, NXD_ADDRESS *client_address, UINT client_state, 
                                  ULONG IP_lease_time_accrued, ULONG valid_lifetime, UINT duid_type,  UINT duid_hardware, ULONG physical_address_msw, 
                                  ULONG physical_address_lsw, ULONG duid_time, ULONG duid_vendor_number, UCHAR *duid_vendor_private, UINT duid_private_length)
{
UINT i;
UINT found = NX_FALSE;
NX_DHCPV6_CLIENT *dhcpv6_client_ptr; 
    if (table_index != 0xFFFFFFFF)
    {
        if (table_index >= NX_DHCPV6_MAX_CLIENTS)
        {
            return NX_INVALID_PARAMETERS;
        }
        if (dhcpv6_server_ptr -> nx_dhcpv6_clients[table_index].nx_dhcpv6_message_xid != 0)
        {
            table_index = 0xFFFFFFFF;
        }
    }
    if (table_index == 0xFFFFFFFF)
    {
        for (i = 0; i < NX_DHCPV6_MAX_CLIENTS; i++)
        {
            if (dhcpv6_server_ptr -> nx_dhcpv6_clients[i].nx_dhcpv6_message_xid == 0)
            {
                table_index = i;
                break;
            }
        }
        if (i == NX_DHCPV6_MAX_CLIENTS)
        {
            return NX_DHCPV6_TABLE_FULL;
        }
    }
    dhcpv6_client_ptr =  &(dhcpv6_server_ptr -> nx_dhcpv6_clients[table_index]);
    dhcpv6_client_ptr -> nx_dhcpv6_id = NX_DHCPV6_CLIENT_ID;
    dhcpv6_client_ptr -> nx_dhcpv6_message_xid = message_xid;
    dhcpv6_client_ptr -> nx_dhcpv6_state = (UCHAR)client_state;
    dhcpv6_client_ptr -> nx_dhcpv6_IP_lease_time_accrued  = IP_lease_time_accrued;
    memcpy(&(dhcpv6_client_ptr -> nx_dhcpv6_server_duid), &(dhcpv6_server_ptr -> nx_dhcpv6_server_duid), sizeof(NX_DHCPV6_SVR_DUID)); 
    dhcpv6_client_ptr -> nx_dhcpv6_client_duid.nx_op_code = NX_DHCPV6_OP_DUID_CLIENT;
    dhcpv6_client_ptr -> nx_dhcpv6_client_duid.nx_hardware_type = (USHORT)duid_hardware;
    dhcpv6_client_ptr -> nx_dhcpv6_client_duid.nx_duid_type = (USHORT)duid_type;
    if (duid_type == NX_DHCPV6_SERVER_DUID_TYPE_VENDOR_ASSIGNED)
    {
        if (duid_private_length > NX_DHCPV6_SERVER_DUID_VENDOR_ASSIGNED_LENGTH)
        {
            return NX_DHCPV6_INVALID_DUID;
        }
        dhcpv6_client_ptr -> nx_dhcpv6_client_duid.nx_duid_enterprise_number = duid_vendor_number;
        memcpy(&(dhcpv6_client_ptr -> nx_dhcpv6_client_duid.nx_duid_private_identifier[0]), duid_vendor_private, duid_private_length); 
        dhcpv6_client_ptr -> nx_dhcpv6_client_duid.nx_option_length = (USHORT)(duid_private_length + 6);
    }
    else 
    {
        dhcpv6_client_ptr -> nx_dhcpv6_client_duid.nx_link_layer_address_msw = (USHORT)physical_address_msw;
        dhcpv6_client_ptr -> nx_dhcpv6_client_duid.nx_link_layer_address_lsw = physical_address_lsw;
        dhcpv6_client_ptr -> nx_dhcpv6_client_duid.nx_option_length = 10;
        if (duid_type == NX_DHCPV6_SERVER_DUID_TYPE_LINK_TIME)
        {
            dhcpv6_client_ptr -> nx_dhcpv6_client_duid.nx_option_length = 14;
            dhcpv6_client_ptr -> nx_dhcpv6_client_duid.nx_duid_time = duid_time;
        }
    }
    dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_op_code = NX_DHCPV6_OP_IA_ADDRESS;
    dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_option_length = 24;
    dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_valid_lifetime = valid_lifetime;
    dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_preferred_lifetime = 0; 
    COPY_NXD_ADDRESS(client_address, &(dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_global_address));
    dhcpv6_client_ptr -> nx_dhcpv6_iana_status.nx_op_code = NX_DHCPV6_OP_OPTION_STATUS;
    dhcpv6_client_ptr -> nx_dhcpv6_iana_status.nx_option_length = 2; 
    dhcpv6_client_ptr -> nx_dhcpv6_iana_status.nx_status_code = NX_DHCPV6_STATUS_SUCCESS;
    for (i = 0; i < NX_DHCPV6_MAX_LEASES; i++)
    {
        if(CHECK_IPV6_ADDRESSES_SAME(&(client_address -> nxd_ip_address.v6[0]), 
                                     &(dhcpv6_server_ptr -> nx_dhcpv6_lease_list[i].nx_dhcpv6_lease_IP_address.nxd_ip_address.v6[0])))
        {
            dhcpv6_server_ptr -> nx_dhcpv6_lease_list[i].nx_dhcpv6_lease_assigned_to = dhcpv6_client_ptr;
            found = NX_TRUE;
            break;
        }
    }
    if (!found)
    {
        return NX_DHCPV6_ADDRESS_NOT_FOUND;
    }
    return NX_SUCCESS;
}
UINT _nx_dhcpv6_add_client_record ( NX_DHCPV6_SERVER * dhcpv6_server_ptr , UINT table_index , ULONG message_xid , NXD_ADDRESS * client_address , UINT client_state , ULONG IP_lease_time_accrued , ULONG valid_lifetime , UINT duid_type , UINT duid_hardware , ULONG physical_address_msw , ULONG physical_address_lsw , ULONG duid_time , ULONG duid_vendor_number , UCHAR * duid_vendor_private , UINT duid_private_length ) { UINT i ; UINT found = NX_FALSE ; NX_DHCPV6_CLIENT * dhcpv6_client_ptr ; if ( table_index != 0xFFFFFFFF ) { if ( table_index >= NX_DHCPV6_MAX_CLIENTS ) { return NX_INVALID_PARAMETERS ; } if ( dhcpv6_server_ptr -> nx_dhcpv6_clients [ table_index ] . nx_dhcpv6_message_xid != 0 ) { table_index = 0xFFFFFFFF ; } } if ( table_index == 0xFFFFFFFF ) { for ( i = 0 ; i < NX_DHCPV6_MAX_CLIENTS ; i ++ ) { if ( dhcpv6_server_ptr -> nx_dhcpv6_clients [ i ] . nx_dhcpv6_message_xid == 0 ) { table_index = i ; break ; } } if ( i == NX_DHCPV6_MAX_CLIENTS ) { return NX_DHCPV6_TABLE_FULL ; } } dhcpv6_client_ptr = & ( dhcpv6_server_ptr -> nx_dhcpv6_clients [ table_index ] ) ; dhcpv6_client_ptr -> nx_dhcpv6_id = NX_DHCPV6_CLIENT_ID ; dhcpv6_client_ptr -> nx_dhcpv6_message_xid = message_xid ; dhcpv6_client_ptr -> nx_dhcpv6_state = ( UCHAR ) client_state ; dhcpv6_client_ptr -> nx_dhcpv6_IP_lease_time_accrued = IP_lease_time_accrued ; memcpy ( & ( dhcpv6_client_ptr -> nx_dhcpv6_server_duid ) , & ( dhcpv6_server_ptr -> nx_dhcpv6_server_duid ) , sizeof ( NX_DHCPV6_SVR_DUID ) ) ; dhcpv6_client_ptr -> nx_dhcpv6_client_duid . nx_op_code = NX_DHCPV6_OP_DUID_CLIENT ; dhcpv6_client_ptr -> nx_dhcpv6_client_duid . nx_hardware_type = ( USHORT ) duid_hardware ; dhcpv6_client_ptr -> nx_dhcpv6_client_duid . nx_duid_type = ( USHORT ) duid_type ; if ( duid_type == NX_DHCPV6_SERVER_DUID_TYPE_VENDOR_ASSIGNED ) { if ( duid_private_length > NX_DHCPV6_SERVER_DUID_VENDOR_ASSIGNED_LENGTH ) { return NX_DHCPV6_INVALID_DUID ; } dhcpv6_client_ptr -> nx_dhcpv6_client_duid . nx_duid_enterprise_number = duid_vendor_number ; memcpy ( & ( dhcpv6_client_ptr -> nx_dhcpv6_client_duid . nx_duid_private_identifier [ 0 ] ) , duid_vendor_private , duid_private_length ) ; dhcpv6_client_ptr -> nx_dhcpv6_client_duid . nx_option_length = ( USHORT ) ( duid_private_length + 6 ) ; } else { dhcpv6_client_ptr -> nx_dhcpv6_client_duid . nx_link_layer_address_msw = ( USHORT ) physical_address_msw ; dhcpv6_client_ptr -> nx_dhcpv6_client_duid . nx_link_layer_address_lsw = physical_address_lsw ; dhcpv6_client_ptr -> nx_dhcpv6_client_duid . nx_option_length = 10 ; if ( duid_type == NX_DHCPV6_SERVER_DUID_TYPE_LINK_TIME ) { dhcpv6_client_ptr -> nx_dhcpv6_client_duid . nx_option_length = 14 ; dhcpv6_client_ptr -> nx_dhcpv6_client_duid . nx_duid_time = duid_time ; } } dhcpv6_client_ptr -> nx_dhcpv6_ia . nx_op_code = NX_DHCPV6_OP_IA_ADDRESS ; dhcpv6_client_ptr -> nx_dhcpv6_ia . nx_option_length = 24 ; dhcpv6_client_ptr -> nx_dhcpv6_ia . nx_valid_lifetime = valid_lifetime ; dhcpv6_client_ptr -> nx_dhcpv6_ia . nx_preferred_lifetime = 0 ; COPY_NXD_ADDRESS ( client_address , & ( dhcpv6_client_ptr -> nx_dhcpv6_ia . nx_global_address ) ) ; dhcpv6_client_ptr -> nx_dhcpv6_iana_status . nx_op_code = NX_DHCPV6_OP_OPTION_STATUS ; dhcpv6_client_ptr -> nx_dhcpv6_iana_status . nx_option_length = 2 ; dhcpv6_client_ptr -> nx_dhcpv6_iana_status . nx_status_code = NX_DHCPV6_STATUS_SUCCESS ; for ( i = 0 ; i < NX_DHCPV6_MAX_LEASES ; i ++ ) { if ( CHECK_IPV6_ADDRESSES_SAME ( & ( client_address -> nxd_ip_address . v6 [ 0 ] ) , & ( dhcpv6_server_ptr -> nx_dhcpv6_lease_list [ i ] . nx_dhcpv6_lease_IP_address . nxd_ip_address . v6 [ 0 ] ) ) ) { dhcpv6_server_ptr -> nx_dhcpv6_lease_list [ i ] . nx_dhcpv6_lease_assigned_to = dhcpv6_client_ptr ; found = NX_TRUE ; break ; } } if ( ! found ) { return NX_DHCPV6_ADDRESS_NOT_FOUND ; } return NX_SUCCESS ; }
FUNCTION                                               RELEASE
FUNCTION RELEASE
/* Check if a table index was specified. */ /* Check if it is a valid index. */ /* No, return a parameter error. */ /* Check if it is actually empty. */ /* Not empty. Indicate we'll have to find an empty slot. */ /* Check if we still need to find a slot. */ /* We do, so loop through client records to find one. */ /* Is this an empty slot? */ /* This is available. */ /* Do we have a slot?  */ /* No, Indicate the table is full. */ /* Create the table entry. */ /* Fill in the generic client information. */ /* Use case of memcpy is verified. */ /*Fill in the Client DUID information. */ /* Determine DUID type to fill in the rest of the DUID fields. */ /* Validate the DUID private length. */ /* Use case of memcpy is verified. */ /* Either link layer or link layer plus time. */ /* Fill in the necessary IA-NA and IA Address option fields. */ /* Don't care */ /* No message */ /* Now access the server lease table to find this client's lease. */ /* Compare our client's assigned IP address with this lease table entry. */ /* They match! Cross link the tables. */ /* This client apparently does not have a valid IP lease. Ok to keep in the tables,
           but they will need to request an IP address! */