/**
 * ============================================================================
 * = COPYRIGHT
 *              INTEL CORPORATION PROPRIETARY INFORMATION
 *   This software is supplied under the terms of a license agreement or
 *   nondisclosure agreement with Intel Corporation and may not be copied 
 *   or disclosed except in accordance with the terms in that agreement.
 *      Copyright (C) 2000-2001 Intel Corporation. All rights reserved.
 *
 * 
 * = MODULE
 *      IPv4 Fwdr CC module
 *
 * = FILENAME
 *      utils.c
 *
 * = DESCRIPTION
 *   This file contains implementation of utility functions to 
 *   calculate checksum for IP packet, printing of IP header,
 *   calculation of unique value for IP header   
 *
 *      
 *
 * = CREATION TIME
 *      07/30/2002 8:00:24 PM
 *
 * = CHANGE HISTORY
 *
 * ============================================================================
 */

#define IX_ERROR_FILE_IDENT "$Id: utils.c,v 1.9 2003/11/04 21:13:54 rranjeet Exp $"


/**
 * System defined include files required.
 */
/**
 * User defined include files required.
 */
#include "ix_cc_error.h"
#include "cc/ipv4/internal/utils.h"
/**
 * Preprocessor symbols and macros used in this file.
 */

/**
 * Types definitions whose scope is limited to this file.
 */

/**
 * Variable declarations global to this file only.  Externs are followed by
 * static variables.
 */
/* Identification field initial value */
static ix_uint16 ix_cc_ipv4_ipID = 0x8000;
/**
 * Extern function prototypes.
 */
/**
 * Static function prototypes.
 */

/**
 * Function definitions.
 */



ix_uint16 _ix_cc_ipv4_get_ip_id()
{

    if ( ++ix_cc_ipv4_ipID == 0xffff )
    {
        ix_cc_ipv4_ipID = 0x8000;
    }
    return ix_cc_ipv4_ipID;

}


/* Checksum calculation function according to RFC1071 */
ix_uint16 _ix_cc_ipv4_calculate_checksum( ix_uint8 *arg_pAddr, ix_uint32 arg_Size )
{

    ix_int32 sum = 0;
    while ( arg_Size > 1 )
    {
        sum += *(ix_uint16 *)(void *)arg_pAddr;
        arg_pAddr += 2;
        arg_Size -= 2;
    }
    if ( arg_Size > 0 )
    {
        sum += *(ix_uint8 *)arg_pAddr;
    }
    while ( sum >> 16 ) 
    {
        sum = ( sum & 0xffff ) + ( sum >> 16 );
    }
    return ((ix_uint16)~sum);
}



ix_uint32 _ix_cc_ipv4_init_ip_header(
           	 ix_uint8 *arg_pData,
                 ix_cc_ipv4_header *arg_pIpHdr)
{
    ix_uint32 len;
    ix_uint8 *pTemp;
    ix_uint8 temp;
    
     
    pTemp = (ix_uint8 *)arg_pData;
    temp = *pTemp;
    len = (ix_uint32)((temp & 0x0f) << 2);
    ix_ossl_memcpy(arg_pIpHdr, arg_pData, len);
    return len;
}


void _ix_cc_ipv4_print_iphdr( ix_uint8 *arg_pHdr )
{

    ix_cc_ipv4_header header;
    ix_ossl_memcpy( &header, arg_pHdr, MIN_IP_LEN ); 
    ix_ossl_message_log( "  version %d\n", header.version );
    ix_ossl_message_log( "  header length %x\n", header.headerLength );
    ix_ossl_message_log( "  TOS %d\n", header.tos );
    ix_ossl_message_log( "  total length %x\n", header.totalLength );
    ix_ossl_message_log( "  ID %x\n", header.id );
#if IX_BYTE_ORDER == IX_LITTLE_ENDIAN
    ix_ossl_message_log( "  flags & frag offset %x\n", header.fragOffset );
#elif IX_BYTE_ORDER == IX_BIG_ENDIAN
    ix_ossl_message_log( "  flags %x\n", header.flags );
    ix_ossl_message_log( "  offset %x\n", header.offset );
#endif
    ix_ossl_message_log( "  TTL %x\n", header.ttl );
    ix_ossl_message_log( "  protocol %x\n", header.protocol );
    ix_ossl_message_log( "  checksum 0x%x\n", header.checksum );
   
    ix_ossl_message_log("source addr = %lx\n", header.sourceAddress);
    ix_ossl_message_log("dest addr = %lx\n", header.destAddress);
   
    if ( header.headerLength > 5 )
    {
        ix_ossl_message_log( "Options:\n" );

        if ( arg_pHdr[20] != 0x83 ) {
            ix_ossl_message_log( "unknown type\n" );
            return;
        }
        ix_ossl_message_log( "Type 0x%x Length %x  Pointer %x\n",
            arg_pHdr[20], arg_pHdr[21], arg_pHdr[22]);
        
        
    }
}




