AzureMXChip/MXCHIPAZ3166/core/lib/netxduo/addons/dhcp/nxd_dhcpv6_server.c
UINT _nx_dhcpv6_server_add_iana(NX_DHCPV6_SERVER *dhcpv6_server_ptr, NX_DHCPV6_CLIENT *dhcpv6_client_ptr, UCHAR *buffer_ptr, UINT *index)
{

UINT            status;
UINT            add_ia;
UINT            temp;
UINT            temp_index;
ULONG           message_word;
UINT            available_payload;
NX_DHCPV6_SERVER_IA_NA *iana_ptr;


    /* Initialize the completion status variable. */
    status = NX_SUCCESS;

    /* Compute the available payload in the packet buffer. */
    available_payload = dhcpv6_server_ptr -> nx_dhcpv6_packet_pool_ptr -> nx_packet_pool_payload_size - 
                        NX_IPv6_UDP_PACKET - *index;

    iana_ptr = &dhcpv6_client_ptr -> nx_dhcpv6_iana;

    /* Check if the client IANA will fit in the packet buffer. */
    if (available_payload < (UINT)(iana_ptr -> nx_option_length + 4)) 
    {

        /* Hmmm... not enough! Can't do it. */
        return NX_DHCPV6_INSUFFICIENT_PACKET_PAYLOAD;
    }

    /* For release or decline messages, or a server status indicating no IP address can be 
       assigned yet, set the IANA IP lease times to expired. */
    if ((dhcpv6_client_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_RELEASE) ||
        (dhcpv6_client_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_DECLINE) ||
        (dhcpv6_client_ptr -> nx_dhcpv6_iana_status.nx_status_code != NX_DHCPV6_STATUS_SUCCESS))
    {

        iana_ptr -> nx_T1 = 0;
        iana_ptr -> nx_T2 = 0;

        dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_preferred_lifetime = 0;
        dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_valid_lifetime = 0;
    }

    /* Clear memory to make the first word of the IA-NA header. */
    memset(&message_word, 0, sizeof(ULONG));

    /* Save this location in the buffer. */
    temp_index = *index;

    /* Write the IANA opcode and data length into one word. */
    message_word = (ULONG)((iana_ptr -> nx_op_code) << 16); 

    /* Reset the IANA length to just the IANA option fields, (not IA or status options). */
    iana_ptr -> nx_option_length = 3 * sizeof(ULONG);

    message_word |= iana_ptr -> nx_option_length;

    /* Adjust for endianness. */
    NX_CHANGE_ULONG_ENDIAN(message_word);

    /* Copy the word into the packet buffer going to the server. */
    memcpy(buffer_ptr + *index, &message_word, sizeof(ULONG)); /* Use case of memcpy is verified. */

    /* Update the buffer pointer. */
    *index += (ULONG)sizeof(ULONG);

    /* Adjust for endianness. */
    NX_CHANGE_ULONG_ENDIAN(iana_ptr -> nx_IA_NA_id);
    NX_CHANGE_ULONG_ENDIAN(iana_ptr -> nx_T1);
    NX_CHANGE_ULONG_ENDIAN(iana_ptr -> nx_T2);

    memcpy(buffer_ptr + *index, &(iana_ptr -> nx_IA_NA_id), sizeof(ULONG)); /* Use case of memcpy is verified. */
    *index += (ULONG)sizeof(ULONG);

    memcpy(buffer_ptr + *index, &(iana_ptr -> nx_T1), sizeof(ULONG)); /* Use case of memcpy is verified. */
    *index += (ULONG)sizeof(ULONG);

    memcpy(buffer_ptr + *index, &(iana_ptr -> nx_T2), sizeof(ULONG)); /* Use case of memcpy is verified. */
    *index += (ULONG)sizeof(ULONG);

    /* Swap bytes back. */
    NX_CHANGE_ULONG_ENDIAN(iana_ptr -> nx_IA_NA_id);
    NX_CHANGE_ULONG_ENDIAN(iana_ptr -> nx_T1);
    NX_CHANGE_ULONG_ENDIAN(iana_ptr -> nx_T2);

    /* Determine if we include an IA address option. This requires a successful IANA status
       and applies only if the client is requesting or confirming an address including renew/rebinding one. */
    add_ia = NX_FALSE;

    /* We include an IA if we intend to assign or confirm an IP address. */
    if (dhcpv6_client_ptr -> nx_dhcpv6_iana_status.nx_status_code == NX_DHCPV6_STATUS_SUCCESS)
    {
        if ((dhcpv6_client_ptr -> nx_dhcpv6_message_type >= NX_DHCPV6_MESSAGE_TYPE_SOLICIT) &&    
            (dhcpv6_client_ptr -> nx_dhcpv6_message_type <= NX_DHCPV6_MESSAGE_TYPE_DECLINE))
        {

                add_ia = NX_TRUE;
        }
    }

    /* Or if we are confirming the IP address a client is releasing or declining, regardless
       if our records show this IP address is bound to this client. Sect 18.2.6-7 RFC 3315. */
    if ((dhcpv6_client_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_RELEASE) ||    
            (dhcpv6_client_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_DECLINE))
    {
        add_ia = NX_TRUE;
    }

    if (add_ia)
    {

        temp = *index;

        /* Check for a missing IA option (as in the Solicit message did not have one). */
        if (dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_op_code == 0)
        {

            NX_DHCPV6_ADDRESS_LEASE *client_address_lease; 

            dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_op_code = NX_DHCPV6_OP_IA_ADDRESS;
    
            /* Set the length to include option code, lenght (one word), IPv6 address (4 words), and lifetime data (2 words). */
            dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_option_length = (2 * sizeof(ULONG))+ (4 * sizeof(ULONG));
    
            dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_preferred_lifetime = NX_DHCPV6_DEFAULT_PREFERRED_TIME;
    
            dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_valid_lifetime= NX_DHCPV6_DEFAULT_VALID_TIME;
    
            /* Find the Client's tentatively assigned address in the Server IP address list. */
            _nx_dhcpv6_find_ip_address(dhcpv6_server_ptr, dhcpv6_client_ptr, &client_address_lease);

            if ((status != NX_SUCCESS) || (client_address_lease == NX_NULL))
            {

                return status;
            }

            COPY_IPV6_ADDRESS(&client_address_lease -> nx_dhcpv6_lease_IP_address.nxd_ip_address.v6[0], 
                              &dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_global_address.nxd_ip_address.v6[0]);
        }

        status = _nx_dhcpv6_add_ia(dhcpv6_server_ptr, &dhcpv6_client_ptr -> nx_dhcpv6_ia, buffer_ptr, &temp);

        if (status != NX_SUCCESS)
        {

            return status;
        }


        /* Add the size of the IA(s) to the client IANA. Note that we include the option code
           and length field of any nested options. */
        iana_ptr -> nx_option_length = (USHORT)(iana_ptr -> nx_option_length + dhcpv6_client_ptr-> nx_dhcpv6_ia.nx_option_length + 4);

        /* Update the index into packet buffer from our temporary variable. */
        *index = temp;
    }

    /* Update the IANA status message. */
    status = _nx_dhcpv6_prepare_iana_status(&dhcpv6_client_ptr -> nx_dhcpv6_iana_status, NX_TRUE);

    if (status != NX_SUCCESS)
    {

        return status;
    }

    temp = *index;
    
    /* Ok to add one to server reply.*/
    status = _nx_dhcpv6_add_iana_status(dhcpv6_server_ptr, &dhcpv6_client_ptr -> nx_dhcpv6_iana_status, buffer_ptr, &temp);

    if (status != NX_SUCCESS)
    {

        return status;
    }

    /* Update the index into packet buffer from our temporary variable. */
    *index = temp;

    /* Update the IANA option length with the iana status option size. */
    iana_ptr -> nx_option_length = (USHORT)(iana_ptr -> nx_option_length + dhcpv6_client_ptr->nx_dhcpv6_iana_status.nx_option_length + 4);

    /* Rewrite the IANA opcode and update the changed IANA data length with the additional IA address option. */
    message_word = (ULONG)((iana_ptr -> nx_op_code) << 16);
    message_word |= (ULONG)(iana_ptr -> nx_option_length);

    /* Adjust for endianness. */
    NX_CHANGE_ULONG_ENDIAN(message_word);

    /* Copy the updated word into the packet buffer at the saved location. */
    memcpy(buffer_ptr + temp_index, &message_word, sizeof(ULONG)); /* Use case of memcpy is verified. */

    /* Erase the IANA status message. We will add another message on the next (if any) IANA option for the client. */
    status = _nx_dhcpv6_prepare_iana_status(&dhcpv6_client_ptr -> nx_dhcpv6_iana_status, NX_FALSE);

    return status;
}
/**************************************************************************/
/*                                                                        */
/*  FUNCTION                                               RELEASE        */
/*                                                                        */
/*    _nx_dhcpv6_server_add_iana                          PORTABLE C      */
/*                                                           6.1          */
/*  AUTHOR                                                                */
/*                                                                        */
/*    Yuxin Zhou, Microsoft Corporation                                   */
/*                                                                        */
/*  DESCRIPTION                                                           */
/*                                                                        */
/*    This function adds the IANA option to the server response  packet   */
/*    using the Client IANA on record.  It will also add any 'nested'     */
/*    options such as the Client IA(s) and IANA status option.            */
/*                                                                        */
/*  INPUT                                                                 */
/*                                                                        */
/*    dhcpv6_server_ptr                 Pointer to DHCPV6 server instance */
/*    dhcpv6_client_ptr                 Pointer to DHCPV6 client instance */
/*    buffer_ptr                        Pointer to response packet buffer */
/*    index                             Location into buffer to write data*/
/*                                                                        */
/*  OUTPUT                                                                */
/*                                                                        */
/*    status                            Actual completion status          */
/*    NX_DHCPV6_INSUFFICIENT_PACKET_PAYLOAD                               */
/*                                      Buffer too small for IANA option  */
/*  CALLS                                                                 */
/*                                                                        */
/*    _nx_dhcpv6_add_ia                 Adds the IA option to buffer      */
/*    memset                            Clears specified area of memory   */
/*    memcpy                            Copies specified area of memory   */
/*                                                                        */
/*  CALLED BY                                                             */
/*                                                                        */
/*    _nx_dhcpv6_send_request           Sends server DHCPv6 response      */
/*                                                                        */
/*  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_server_add_iana                          PORTABLE C
6.1
AUTHOR

Yuxin Zhou, Microsoft Corporation

DESCRIPTION

This function adds the IANA option to the server response  packet
using the Client IANA on record.  It will also add any 'nested'
options such as the Client IA(s) and IANA status option.

INPUT

dhcpv6_server_ptr                 Pointer to DHCPV6 server instance
dhcpv6_client_ptr                 Pointer to DHCPV6 client instance
buffer_ptr                        Pointer to response packet buffer
index                             Location into buffer to write data

OUTPUT

status                            Actual completion status
NX_DHCPV6_INSUFFICIENT_PACKET_PAYLOAD
Buffer too small for IANA option
CALLS

_nx_dhcpv6_add_ia                 Adds the IA option to buffer
memset                            Clears specified area of memory
memcpy                            Copies specified area of memory

CALLED BY



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_server_add_iana PORTABLE C 6 . 1 AUTHOR Yuxin Zhou Microsoft Corporation DESCRIPTION This function adds the IANA option to the server response packet using the Client IANA on record . It will also add any ' nested ' options such as the Client IA ( s ) and IANA status option . INPUT dhcpv6_server_ptr Pointer to DHCPV6 server instance dhcpv6_client_ptr Pointer to DHCPV6 client instance buffer_ptr Pointer to response packet buffer index Location into buffer to write data OUTPUT status Actual completion status NX_DHCPV6_INSUFFICIENT_PACKET_PAYLOAD Buffer too small for IANA option CALLS _nx_dhcpv6_add_ia Adds the IA option to buffer memset Clears specified area of memory memcpy Copies specified area of memory CALLED BY 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_server_add_iana(NX_DHCPV6_SERVER *dhcpv6_server_ptr, NX_DHCPV6_CLIENT *dhcpv6_client_ptr, UCHAR *buffer_ptr, UINT *index)
{
UINT            status;
UINT            add_ia;
UINT            temp;
UINT            temp_index;
ULONG           message_word;
UINT            available_payload;
NX_DHCPV6_SERVER_IA_NA *iana_ptr;
    status = NX_SUCCESS;
    available_payload = dhcpv6_server_ptr -> nx_dhcpv6_packet_pool_ptr -> nx_packet_pool_payload_size - 
                        NX_IPv6_UDP_PACKET - *index;
    iana_ptr = &dhcpv6_client_ptr -> nx_dhcpv6_iana;
    if (available_payload < (UINT)(iana_ptr -> nx_option_length + 4)) 
    {
        return NX_DHCPV6_INSUFFICIENT_PACKET_PAYLOAD;
    }
    if ((dhcpv6_client_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_RELEASE) ||
        (dhcpv6_client_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_DECLINE) ||
        (dhcpv6_client_ptr -> nx_dhcpv6_iana_status.nx_status_code != NX_DHCPV6_STATUS_SUCCESS))
    {
        iana_ptr -> nx_T1 = 0;
        iana_ptr -> nx_T2 = 0;
        dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_preferred_lifetime = 0;
        dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_valid_lifetime = 0;
    }
    memset(&message_word, 0, sizeof(ULONG));
    temp_index = *index;
    message_word = (ULONG)((iana_ptr -> nx_op_code) << 16); 
    iana_ptr -> nx_option_length = 3 * sizeof(ULONG);
    message_word |= iana_ptr -> nx_option_length;
    NX_CHANGE_ULONG_ENDIAN(message_word);
    memcpy(buffer_ptr + *index, &message_word, sizeof(ULONG)); 
    *index += (ULONG)sizeof(ULONG);
    NX_CHANGE_ULONG_ENDIAN(iana_ptr -> nx_IA_NA_id);
    NX_CHANGE_ULONG_ENDIAN(iana_ptr -> nx_T1);
    NX_CHANGE_ULONG_ENDIAN(iana_ptr -> nx_T2);
    memcpy(buffer_ptr + *index, &(iana_ptr -> nx_IA_NA_id), sizeof(ULONG)); 
    *index += (ULONG)sizeof(ULONG);
    memcpy(buffer_ptr + *index, &(iana_ptr -> nx_T1), sizeof(ULONG)); 
    *index += (ULONG)sizeof(ULONG);
    memcpy(buffer_ptr + *index, &(iana_ptr -> nx_T2), sizeof(ULONG)); 
    *index += (ULONG)sizeof(ULONG);
    NX_CHANGE_ULONG_ENDIAN(iana_ptr -> nx_IA_NA_id);
    NX_CHANGE_ULONG_ENDIAN(iana_ptr -> nx_T1);
    NX_CHANGE_ULONG_ENDIAN(iana_ptr -> nx_T2);
    add_ia = NX_FALSE;
    if (dhcpv6_client_ptr -> nx_dhcpv6_iana_status.nx_status_code == NX_DHCPV6_STATUS_SUCCESS)
    {
        if ((dhcpv6_client_ptr -> nx_dhcpv6_message_type >= NX_DHCPV6_MESSAGE_TYPE_SOLICIT) &&    
            (dhcpv6_client_ptr -> nx_dhcpv6_message_type <= NX_DHCPV6_MESSAGE_TYPE_DECLINE))
        {
                add_ia = NX_TRUE;
        }
    }
    if ((dhcpv6_client_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_RELEASE) ||    
            (dhcpv6_client_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_DECLINE))
    {
        add_ia = NX_TRUE;
    }
    if (add_ia)
    {
        temp = *index;
        if (dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_op_code == 0)
        {
            NX_DHCPV6_ADDRESS_LEASE *client_address_lease; 
            dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_op_code = NX_DHCPV6_OP_IA_ADDRESS;
            dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_option_length = (2 * sizeof(ULONG))+ (4 * sizeof(ULONG));
            dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_preferred_lifetime = NX_DHCPV6_DEFAULT_PREFERRED_TIME;
            dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_valid_lifetime= NX_DHCPV6_DEFAULT_VALID_TIME;
            _nx_dhcpv6_find_ip_address(dhcpv6_server_ptr, dhcpv6_client_ptr, &client_address_lease);
            if ((status != NX_SUCCESS) || (client_address_lease == NX_NULL))
            {
                return status;
            }
            COPY_IPV6_ADDRESS(&client_address_lease -> nx_dhcpv6_lease_IP_address.nxd_ip_address.v6[0], 
                              &dhcpv6_client_ptr -> nx_dhcpv6_ia.nx_global_address.nxd_ip_address.v6[0]);
        }
        status = _nx_dhcpv6_add_ia(dhcpv6_server_ptr, &dhcpv6_client_ptr -> nx_dhcpv6_ia, buffer_ptr, &temp);
        if (status != NX_SUCCESS)
        {
            return status;
        }
        iana_ptr -> nx_option_length = (USHORT)(iana_ptr -> nx_option_length + dhcpv6_client_ptr-> nx_dhcpv6_ia.nx_option_length + 4);
        *index = temp;
    }
    status = _nx_dhcpv6_prepare_iana_status(&dhcpv6_client_ptr -> nx_dhcpv6_iana_status, NX_TRUE);
    if (status != NX_SUCCESS)
    {
        return status;
    }
    temp = *index;
    status = _nx_dhcpv6_add_iana_status(dhcpv6_server_ptr, &dhcpv6_client_ptr -> nx_dhcpv6_iana_status, buffer_ptr, &temp);
    if (status != NX_SUCCESS)
    {
        return status;
    }
    *index = temp;
    iana_ptr -> nx_option_length = (USHORT)(iana_ptr -> nx_option_length + dhcpv6_client_ptr->nx_dhcpv6_iana_status.nx_option_length + 4);
    message_word = (ULONG)((iana_ptr -> nx_op_code) << 16);
    message_word |= (ULONG)(iana_ptr -> nx_option_length);
    NX_CHANGE_ULONG_ENDIAN(message_word);
    memcpy(buffer_ptr + temp_index, &message_word, sizeof(ULONG)); 
    status = _nx_dhcpv6_prepare_iana_status(&dhcpv6_client_ptr -> nx_dhcpv6_iana_status, NX_FALSE);
    return status;
}
UINT _nx_dhcpv6_server_add_iana ( NX_DHCPV6_SERVER * dhcpv6_server_ptr , NX_DHCPV6_CLIENT * dhcpv6_client_ptr , UCHAR * buffer_ptr , UINT * index ) { UINT status ; UINT add_ia ; UINT temp ; UINT temp_index ; ULONG message_word ; UINT available_payload ; NX_DHCPV6_SERVER_IA_NA * iana_ptr ; status = NX_SUCCESS ; available_payload = dhcpv6_server_ptr -> nx_dhcpv6_packet_pool_ptr -> nx_packet_pool_payload_size - NX_IPv6_UDP_PACKET - * index ; iana_ptr = & dhcpv6_client_ptr -> nx_dhcpv6_iana ; if ( available_payload < ( UINT ) ( iana_ptr -> nx_option_length + 4 ) ) { return NX_DHCPV6_INSUFFICIENT_PACKET_PAYLOAD ; } if ( ( dhcpv6_client_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_RELEASE ) || ( dhcpv6_client_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_DECLINE ) || ( dhcpv6_client_ptr -> nx_dhcpv6_iana_status . nx_status_code != NX_DHCPV6_STATUS_SUCCESS ) ) { iana_ptr -> nx_T1 = 0 ; iana_ptr -> nx_T2 = 0 ; dhcpv6_client_ptr -> nx_dhcpv6_ia . nx_preferred_lifetime = 0 ; dhcpv6_client_ptr -> nx_dhcpv6_ia . nx_valid_lifetime = 0 ; } memset ( & message_word , 0 , sizeof ( ULONG ) ) ; temp_index = * index ; message_word = ( ULONG ) ( ( iana_ptr -> nx_op_code ) << 16 ) ; iana_ptr -> nx_option_length = 3 * sizeof ( ULONG ) ; message_word |= iana_ptr -> nx_option_length ; NX_CHANGE_ULONG_ENDIAN ( message_word ) ; memcpy ( buffer_ptr + * index , & message_word , sizeof ( ULONG ) ) ; * index += ( ULONG ) sizeof ( ULONG ) ; NX_CHANGE_ULONG_ENDIAN ( iana_ptr -> nx_IA_NA_id ) ; NX_CHANGE_ULONG_ENDIAN ( iana_ptr -> nx_T1 ) ; NX_CHANGE_ULONG_ENDIAN ( iana_ptr -> nx_T2 ) ; memcpy ( buffer_ptr + * index , & ( iana_ptr -> nx_IA_NA_id ) , sizeof ( ULONG ) ) ; * index += ( ULONG ) sizeof ( ULONG ) ; memcpy ( buffer_ptr + * index , & ( iana_ptr -> nx_T1 ) , sizeof ( ULONG ) ) ; * index += ( ULONG ) sizeof ( ULONG ) ; memcpy ( buffer_ptr + * index , & ( iana_ptr -> nx_T2 ) , sizeof ( ULONG ) ) ; * index += ( ULONG ) sizeof ( ULONG ) ; NX_CHANGE_ULONG_ENDIAN ( iana_ptr -> nx_IA_NA_id ) ; NX_CHANGE_ULONG_ENDIAN ( iana_ptr -> nx_T1 ) ; NX_CHANGE_ULONG_ENDIAN ( iana_ptr -> nx_T2 ) ; add_ia = NX_FALSE ; if ( dhcpv6_client_ptr -> nx_dhcpv6_iana_status . nx_status_code == NX_DHCPV6_STATUS_SUCCESS ) { if ( ( dhcpv6_client_ptr -> nx_dhcpv6_message_type >= NX_DHCPV6_MESSAGE_TYPE_SOLICIT ) && ( dhcpv6_client_ptr -> nx_dhcpv6_message_type <= NX_DHCPV6_MESSAGE_TYPE_DECLINE ) ) { add_ia = NX_TRUE ; } } if ( ( dhcpv6_client_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_RELEASE ) || ( dhcpv6_client_ptr -> nx_dhcpv6_message_type == NX_DHCPV6_MESSAGE_TYPE_DECLINE ) ) { add_ia = NX_TRUE ; } if ( add_ia ) { temp = * index ; if ( dhcpv6_client_ptr -> nx_dhcpv6_ia . nx_op_code == 0 ) { NX_DHCPV6_ADDRESS_LEASE * client_address_lease ; dhcpv6_client_ptr -> nx_dhcpv6_ia . nx_op_code = NX_DHCPV6_OP_IA_ADDRESS ; dhcpv6_client_ptr -> nx_dhcpv6_ia . nx_option_length = ( 2 * sizeof ( ULONG ) ) + ( 4 * sizeof ( ULONG ) ) ; dhcpv6_client_ptr -> nx_dhcpv6_ia . nx_preferred_lifetime = NX_DHCPV6_DEFAULT_PREFERRED_TIME ; dhcpv6_client_ptr -> nx_dhcpv6_ia . nx_valid_lifetime = NX_DHCPV6_DEFAULT_VALID_TIME ; _nx_dhcpv6_find_ip_address ( dhcpv6_server_ptr , dhcpv6_client_ptr , & client_address_lease ) ; if ( ( status != NX_SUCCESS ) || ( client_address_lease == NX_NULL ) ) { return status ; } COPY_IPV6_ADDRESS ( & client_address_lease -> nx_dhcpv6_lease_IP_address . nxd_ip_address . v6 [ 0 ] , & dhcpv6_client_ptr -> nx_dhcpv6_ia . nx_global_address . nxd_ip_address . v6 [ 0 ] ) ; } status = _nx_dhcpv6_add_ia ( dhcpv6_server_ptr , & dhcpv6_client_ptr -> nx_dhcpv6_ia , buffer_ptr , & temp ) ; if ( status != NX_SUCCESS ) { return status ; } iana_ptr -> nx_option_length = ( USHORT ) ( iana_ptr -> nx_option_length + dhcpv6_client_ptr -> nx_dhcpv6_ia . nx_option_length + 4 ) ; * index = temp ; } status = _nx_dhcpv6_prepare_iana_status ( & dhcpv6_client_ptr -> nx_dhcpv6_iana_status , NX_TRUE ) ; if ( status != NX_SUCCESS ) { return status ; } temp = * index ; status = _nx_dhcpv6_add_iana_status ( dhcpv6_server_ptr , & dhcpv6_client_ptr -> nx_dhcpv6_iana_status , buffer_ptr , & temp ) ; if ( status != NX_SUCCESS ) { return status ; } * index = temp ; iana_ptr -> nx_option_length = ( USHORT ) ( iana_ptr -> nx_option_length + dhcpv6_client_ptr -> nx_dhcpv6_iana_status . nx_option_length + 4 ) ; message_word = ( ULONG ) ( ( iana_ptr -> nx_op_code ) << 16 ) ; message_word |= ( ULONG ) ( iana_ptr -> nx_option_length ) ; NX_CHANGE_ULONG_ENDIAN ( message_word ) ; memcpy ( buffer_ptr + temp_index , & message_word , sizeof ( ULONG ) ) ; status = _nx_dhcpv6_prepare_iana_status ( & dhcpv6_client_ptr -> nx_dhcpv6_iana_status , NX_FALSE ) ; return status ; }
FUNCTION                                               RELEASE
FUNCTION RELEASE
/* Initialize the completion status variable. */ /* Compute the available payload in the packet buffer. */ /* Check if the client IANA will fit in the packet buffer. */ /* Hmmm... not enough! Can't do it. */ /* For release or decline messages, or a server status indicating no IP address can be 
       assigned yet, set the IANA IP lease times to expired. */ /* Clear memory to make the first word of the IA-NA header. */ /* Save this location in the buffer. */ /* Write the IANA opcode and data length into one word. */ /* Reset the IANA length to just the IANA option fields, (not IA or status options). */ /* Adjust for endianness. */ /* Copy the word into the packet buffer going to the server. */ /* Use case of memcpy is verified. */ /* Update the buffer pointer. */ /* Adjust for endianness. */ /* Use case of memcpy is verified. */ /* Use case of memcpy is verified. */ /* Use case of memcpy is verified. */ /* Swap bytes back. */ /* Determine if we include an IA address option. This requires a successful IANA status
       and applies only if the client is requesting or confirming an address including renew/rebinding one. */ /* We include an IA if we intend to assign or confirm an IP address. */ /* Or if we are confirming the IP address a client is releasing or declining, regardless
       if our records show this IP address is bound to this client. Sect 18.2.6-7 RFC 3315. */ /* Check for a missing IA option (as in the Solicit message did not have one). */ /* Set the length to include option code, lenght (one word), IPv6 address (4 words), and lifetime data (2 words). */ /* Find the Client's tentatively assigned address in the Server IP address list. */ /* Add the size of the IA(s) to the client IANA. Note that we include the option code
           and length field of any nested options. */ /* Update the index into packet buffer from our temporary variable. */ /* Update the IANA status message. */ /* Ok to add one to server reply.*/ /* Update the index into packet buffer from our temporary variable. */ /* Update the IANA option length with the iana status option size. */ /* Rewrite the IANA opcode and update the changed IANA data length with the additional IA address option. */ /* Adjust for endianness. */ /* Copy the updated word into the packet buffer at the saved location. */ /* Use case of memcpy is verified. */ /* Erase the IANA status message. We will add another message on the next (if any) IANA option for the client. */