www.pudn.com > Firewall_PNE_3_3.zip > fwLogLib.c, change:2009-03-16,size:27649b


/* fwLogLib.c - Firewall logging library */

/*
 * Copyright (c) 2004-2006 Wind River Systems, Inc.
 *
 * The right to copy, distribute, modify or otherwise make use
 * of this software may be licensed only pursuant to the terms
 * of an applicable Wind River license agreement.
 */

/*
modification history
--------------------
01j,03mar06,kch  Fixed coverity issues in fwLogTask() and fwMemLogWrite()
                 (SPR#118475).
01i,09mar05,svk  Fix compilation warning
01h,13dec04,myz  added IPV6 support
01g,21jul04,myz  removed ip_id field swapping 
01f,13jul04,myz  port to dual stack
01e,07may04,svk  Fix compilation warning
01d,16mar04,myz added FW_NEXT_RULE and FW_NEXT_RULEGROUP action codes
01c,27feb04,myz removed dependency of SNTP client and syslog client
01b,29jan04,myz added a retrievedNum message display counter
01a,08sep03,myz written
*/

/*
DESCRIPTION

This library provides the Firewall message logging interface and facility.
The logged messages are stored at the given memory space if provided, or a
dynamically allocated space if not provided. The memory space will be 
configured to store and retrieve messages in the first in first out order.If 
the memory is full, the oldest messages will be overwritten. The logging 
facility allows the user to select how the logged messages are displayed, 
either print it on the console or send it to the remote syslog server by 
calling the syslog client API function. The configuration parameters should be
provided when calling fwLogLibInit().

CALLING fwLogLibInit.
There are four passing parameters for this function. The first one has three 
values: FW_LOG_TO_SYSLOG to select the syslog server as logged message's 
output device, FW_LOG_TO_CONSOLE to select target console and 
FW_LOG_TO_NONE not to print out. If syslog server is selected, the next 
parameter should be the default syslog server's IP address. For other two 
choices, it has no meaning. The next two parameters are the start of memory 
location and the size to store the logged messages.  If user does not provide 
these two parameters, this library will dynamically allocate a chunk of memory
with default size of 64k bytes. 

TIMESTAMP
The logging facility assigns a timestamp to each log message. The timestamp is
retrieved from the POSIX clock on the target. It is assumed this clock
should be already set up correctly by the system software. If not, user can
use functions fwClockTimeSet() or fwClockBaseInit() in fwUtilLib.c to set the
clock. The first function allows the user to synchronize the target clock with
NTP time server by calling the SNTP client function. The NTP time server IP 
address should be provided when calling this function. The TIMEZONE environment
variable should also be set. Otherwise the PDT time zone is assumed. For example
to set to the PDT time zone:  putenv("TIMEZONE=PDT::480:040102:102802"). 
The TIMEZONE is of the form: <name_of_zone>:<(unused)>: 
<time_in_minutes_from_UTC>: <daylight_start>:<daylight_end>. Please refer to
ansiTime library manual page for more info. The second function allows the user
manually set the clock with the given time values.

*/

#include "fw.h"
#include "net/ethernet.h"
#include "etherLib.h"
#include "wrn/firewall/syslogcLib.h"

/* macros */

#define MEMLOG_DEFAULT_MEM_SIZE   (64 * 1024)  /* 64K */
#define MEMORY_ALLOCATED       1
#define MEMORY_NOT_ALLOCATED   2
#define ALIGNMENT_4BYTES       4
#define TEMP_BUF_LEN           100
#define IPADDR_STR_SIZE        (INET6_ADDRSTRLEN + 1)
#define BYTE_MS4BITS(x) (((x) >> 4) & 0x0f)
#define BYTE_LS4BITS(x) ((x) & 0x0f)
#define ASCII_ZERO  0x30
#define ASCII_a     0x60

#define ACCEPT_STR_INX      0
#define ASSEMBLE_STR_INX    1
#define NEXT_RULE_STR_INX   2
#define NEXT_GROUP_STR_INX  3
#define REJECT_STR_INX      4

typedef struct 
    {
    char * pMemLoc;    /* the buffer to store all the log messages */
    int    wrInx;      /* write index */
    int    bufLen;     /* the buffer length */
    int    freeLen;    /* free space length */
    int    memFlag;    /* the memory is allocated or passed by user */
    UINT32 overWrittenNum;  /* message overwritten number */
    UINT32 retrievedNum;    /* the number of messages have been retrieved */
    SEM_ID semId;      /* mutual exclusion for read and write */
    SEM_ID wakeupId;   /* signal a new message is logged */
    int    taskId;
    DL_LIST list;
    } MEM_LOG_DESC;

typedef struct {
    DL_NODE node; 
    char * pMsg;   /* point to the message */
    int len;    /* the message length */
    int bufLen;
    } MEM_LOG_NODE;

typedef struct {
    UINT32 code;    /* the message code */
    time_t time;    /* the relative time in seconds */
    } MEM_LOG_MSG_HDR;

/* locals */

LOCAL MEM_LOG_DESC memLogDesc;
LOCAL MEM_LOG_DESC * pMemLogDesc = &memLogDesc;
LOCAL BOOL fwLogLibInitDone = FALSE;
LOCAL volatile int logOutputDevice = FW_LOG_TO_NONE;
LOCAL FUNCPTR pSyslogcInitFunc = NULL;
LOCAL FUNCPTR pSyslogcIfFunc   = NULL;
LOCAL FUNCPTR pSyslogcCloseFunc = NULL;
LOCAL char * actionStrs[] = {"ACCEPT", "ASSEMBLE", "NEXT RULE",
			     "NEXT GROUP","REJECT"};

/* Function prototypes */

LOCAL STATUS fwMemLogInit (char *, int);
LOCAL void fwMemLogShutdown (void);
LOCAL void fwLogTask (void);
LOCAL int binToAscStrConvert (UINT8 *, int, char *, int);
LOCAL void pktHeaderDisplay (UINT32 ,UINT8 *,UINT8 *,int);

/******************************************************************************
*
* fwLogLibInit - initialize the firewall logging facility
*
* This routine initializes the logging facility and configures it with either
* a set of user provided parameters or the default values if not provided.
*
* RETURNS: OK or ERROR
*/

STATUS fwLogLibInit 
    (
    int logOutput,  /* FW_LOG_TO_SYSLOG, _CONSOLE or _NONE*/
    char * pAdrStr,  /* default syslog server IP address string */
    void * param0,   /* memory location */
    void * param1    /* memory size  */ 
    )
    {
    if (fwLogLibInitDone != FALSE)
        return OK;

    if (logOutput == FW_LOG_TO_SYSLOG)
        {
        if (pSyslogcInitFunc)
            {
	    if ((*pSyslogcInitFunc)(pAdrStr) == ERROR)
                return ERROR;
            }
        else
            {
            printf("syslogc client interface is not installed\n");
            return ERROR;
            }
        logOutputDevice = FW_LOG_TO_SYSLOG;
        }    
    else if (logOutput == FW_LOG_TO_CONSOLE)
	logOutputDevice = FW_LOG_TO_CONSOLE;
    else if (logOutput == FW_LOG_TO_NONE)
        logOutputDevice = FW_LOG_TO_NONE;
    else
	{
	printf("fwLogLibInit, ERROR: unsupported Logging Facility type\n");
        return ERROR;
	}

    if (fwMemLogInit((char *)param0,(int)param1) == ERROR)
        return ERROR;
    
    fwLogLibInitDone = TRUE;
    return OK;
    }

/******************************************************************************
*
* fwLogLibClose - shutdown the firewall logging facility
*
* This routine disables the firewall logging facility and reclaims 
* the allocated resource. After calling this function, user can re-enable 
* the logging facility by calling fwLogLibInit().
*
* RETURNS: N/A
*/

void fwLogLibClose (void)
    {
    if (fwLogLibInitDone == FALSE)
        return;

    if (logOutputDevice == FW_LOG_TO_SYSLOG)
	if (pSyslogcCloseFunc)
            (*pSyslogcCloseFunc)(); 

    logOutputDevice = FW_LOG_TO_NONE;
    semGive(pMemLogDesc->wakeupId);

    /* wait for the logRetrieve task to delete itself */

    taskDelay(sysClkRateGet()/8);
    fwMemLogShutdown();
     
    fwLogLibInitDone = FALSE;
    }
 
/******************************************************************************
*
* fwMemLogInit - initialize the memory resource for the logging facility
*
*
* RETURNS: OK or ERROR
*
*/

LOCAL STATUS fwMemLogInit
    (
    char * pMemLoc,
    int    size
    )
    {
    if (!size)
        size = MEMLOG_DEFAULT_MEM_SIZE;

    if (pMemLoc == NULL)
        {
        if ((pMemLoc = malloc(size)) == NULL)
            {
            printf("fwMemLogInit: ERROR, memory allocation fails\n");
            return ERROR;
            }
        pMemLogDesc->memFlag = MEMORY_ALLOCATED;
        }
    else
        {
        pMemLogDesc->memFlag = MEMORY_NOT_ALLOCATED;
        }

    pMemLogDesc->pMemLoc = pMemLoc;
    pMemLogDesc->bufLen  = size;
    pMemLogDesc->wrInx   = 0;
    pMemLogDesc->freeLen = size;
    pMemLogDesc->overWrittenNum = 0;
    pMemLogDesc->retrievedNum = 0;
    dllInit(&pMemLogDesc->list);

    if ((pMemLogDesc->semId = semBCreate(SEM_Q_PRIORITY, SEM_FULL)) == NULL)
        {
        printf("fwMemLogInit: ERROR, fail to create the semaphore\n");
        return ERROR;
        }

    if ((pMemLogDesc->wakeupId = semBCreate(SEM_Q_PRIORITY, SEM_EMPTY)) == NULL)
        {
        printf("fwMemLogInit: ERROR, fail to create the wakeup semaphore\n");
        return ERROR;
        }

    pMemLogDesc->taskId = taskSpawn("tFwlogTask", 200, 0, 5 * 1024, 
		      (FUNCPTR)fwLogTask,
                      1,2,3,4,5,6,7,8,9,10);

    return OK;
    }

/******************************************************************************
*
* fwMemLogShutdown - clean up the memory for the logging facility
*
*/

LOCAL void fwMemLogShutdown (void)
    {
    if (pMemLogDesc->memFlag == MEMORY_ALLOCATED)
        free(pMemLogDesc->pMemLoc);

    semDelete (pMemLogDesc->semId);
    semDelete (pMemLogDesc->wakeupId);
    }

/******************************************************************************
*
* fwMemLogWrite - store the firewall log messages to the memory
*
*
* RETURNS: OK or ERROR
*
*/

LOCAL STATUS fwMemLogWrite
    (
    M_BLK_ID pMblk,  /* mbuf containing the IP packet */
    int len,         /* number of bytes of the packet to be logged */
    UINT32   code,   /* Firewall return action code */
    char * pTag,     /* filter tag */
    UINT32 timeSec   /* time in second from Jan 1 00:00:00 1970 */
    )
    {
    MEM_LOG_NODE * pNode;
    MEM_LOG_NODE * pLastNode;
    MEM_LOG_NODE * pNewNode;
    int bufLen;
    int logLen;
    MEM_LOG_MSG_HDR * pMsgHdr;
    struct ip * pIp;

    if (fwLogLibInitDone == FALSE)
        return ERROR;

    if (len)
        logLen = min(pMblk->m_pkthdr.len, len);
    else
	logLen = pMblk->m_pkthdr.len;

    if (pTag)
        bufLen = ROUND_UP(logLen + strlen(pTag) + sizeof(MEM_LOG_MSG_HDR) +
		      1 + sizeof(MEM_LOG_NODE), ALIGNMENT_4BYTES);
    else
        bufLen = ROUND_UP(logLen + sizeof(MEM_LOG_MSG_HDR) +
		      1 + sizeof(MEM_LOG_NODE), ALIGNMENT_4BYTES);
 
    /* check if have enough space in log buffer, free some if not */

    semTake(pMemLogDesc->semId, WAIT_FOREVER);

    do  { 
        if (bufLen <= pMemLogDesc->freeLen)
	    {
	    /* yes, we have enough space */

            /* check if the buffer will wrap around if the message is stored */

            if (bufLen > (pMemLogDesc->bufLen - pMemLogDesc->wrInx))
                {
                /* yes it does. Messages are only stored in the contiguous
		 * memory. The last chunk of space which can't fit the message
		 * will not be used and simply added to last node. So it won't
		 * be lost
		 */

                pLastNode = (MEM_LOG_NODE *)(pMemLogDesc->list.tail);  
		if (pLastNode)
		    { 
                    pLastNode->bufLen    += (pMemLogDesc->bufLen - 
					     pMemLogDesc->wrInx);

                    pMemLogDesc->freeLen -= (pMemLogDesc->bufLen - 
					     pMemLogDesc->wrInx);

		    /* reset the write index to the beginning of the buffer */

                    pMemLogDesc->wrInx    = 0;
                    }
                else
		    {
		    /* no messages in the buffer, reset */

		    pMemLogDesc->wrInx    = 0;
		    pMemLogDesc->freeLen  = pMemLogDesc->bufLen;
		    }

		/* check if still have enough space after reset write index  */

                if (bufLen <= pMemLogDesc->freeLen)
		    break;  
                }
            else
		break; 
            } 

	/* discard the message to free some space */

	pMemLogDesc->overWrittenNum++;
        pNode = (MEM_LOG_NODE *)dllGet(&pMemLogDesc->list);
        if (pNode)
            pMemLogDesc->freeLen += pNode->bufLen;
        } while (pNode);

    semGive(pMemLogDesc->semId);

    /* safety check */

    if (bufLen > pMemLogDesc->freeLen)
        {
        printf("fwMemLogWrite: ERROR, log buffer too small, can't handle"
	       "the log message with size: 0x%x\n", bufLen);
        return ERROR;
        }

    /* copy data to the buffer */

    pNewNode = (MEM_LOG_NODE *)(pMemLogDesc->pMemLoc + pMemLogDesc->wrInx);
    pNewNode->pMsg = (char *)(pNewNode + 1);
    pMsgHdr = (MEM_LOG_MSG_HDR *)(pNewNode->pMsg);

    /* write the message in this format:
     * -----------------------------------------------------------------
     * msg code | time in sec| filter tag         | packet data
     * -----------------------------------------------------------------
     * 4 bytes    4 bytes      variable string      the packet
     */

    /* the message code */

    pMsgHdr->code = code;

    /* the time in second */

    pMsgHdr->time = timeSec;
    pNewNode->len = sizeof(MEM_LOG_MSG_HDR);

    /* the filter tag */

    if (pTag)
        {
        bcopy(pTag,pNewNode->pMsg + pNewNode->len,strlen(pTag)); 
        pNewNode->len += strlen(pTag);
        }

    pNewNode->pMsg[pNewNode->len] = 0;  /* NULL terminated */
    pNewNode->len++;

    pIp = (struct ip *)(pNewNode->pMsg + pNewNode->len);

    pNewNode->len += netMblkOffsetToBufCopy(
			    pMblk,
			    0,
			    pNewNode->pMsg + pNewNode->len,
			    logLen,
			    NULL);
    if ((code & IPFWF_MODIFY) && 
	(((*(char *)pIp) & IP_VERSION_MASK) == IPV4_VERSION))
        {
        union {
            UINT16 tmpInt16;
            char   tmpInt8[2];
            } holder;

        /* indicate the IP header's fields swapped, revert them back */

        holder.tmpInt16 = ahtons((UINT16 *)pIp + 1);
        *((char *)pIp + 2) = holder.tmpInt8[0];
        *((char *)pIp + 3) = holder.tmpInt8[1];

        holder.tmpInt16 = ahtons(&pIp->ip_off);
        *((char *)(&pIp->ip_off)) = holder.tmpInt8[0];
        *((char *)(&pIp->ip_off) + 1) = holder.tmpInt8[1];
        }
 
    pNewNode->bufLen = bufLen;

    semTake(pMemLogDesc->semId, WAIT_FOREVER);
    pMemLogDesc->wrInx   += bufLen;
    pMemLogDesc->freeLen -= bufLen;
    dllAdd(&pMemLogDesc->list,(DL_NODE *)pNewNode);
    semGive(pMemLogDesc->semId);
    semGive(pMemLogDesc->wakeupId);
    return OK;
    }

/******************************************************************************
*
* fwMemLogRead - retrieve the firewall log messages 
*
*
* RETURNS: OK or ERROR
*
*/

LOCAL int fwMemLogRead 
    (
    char * pBuf,
    int  bufLen
    )
    {
    int copyLen = 0;
    MEM_LOG_NODE * pNode;

    if (fwLogLibInitDone == FALSE)
        return ERROR;

    semTake(pMemLogDesc->semId, WAIT_FOREVER);
    pNode = (MEM_LOG_NODE *)dllGet(&pMemLogDesc->list);

    if (pNode)
        {
        pMemLogDesc->freeLen += pNode->bufLen; 
	    
        copyLen = pNode->len > bufLen? bufLen : pNode->len;
        bcopy(pNode->pMsg,pBuf,copyLen);
        pMemLogDesc->retrievedNum++;
        }

    semGive(pMemLogDesc->semId);
    return copyLen;
    }

/******************************************************************************
*
* fwLogTask - Retrieve the logged message from memory buffer 
*
*
*/

LOCAL void fwLogTask (void)
    {
    char * pMsgBuf;
    char * pPrintBuf;
    int msgLen;
    int msgBufLen;
    MEM_LOG_MSG_HDR * pMsgHdr;
    size_t tmpBufLen;
    int len;
    char * pStr;
    char * pName;
    char * pData;
    char tmpBuf[TEMP_BUF_LEN];

    /* first allocate two buffers for retrieving the message and holding
     * the printable message.
     */

    msgBufLen = 1600;

     /* data buffer */

    if ((pMsgBuf = (char *)malloc(msgBufLen)) == NULL)
        {
        printf("fwLogTask: ERROR: fail to allocate the data buffer\n");
        return;
        }

    pMsgHdr = (MEM_LOG_MSG_HDR *)pMsgBuf;

     /* printable message buffer */

     if ((pPrintBuf = (char *)malloc(3*msgBufLen)) == NULL)
        {
        free(pMsgBuf);
        printf("fwLogTask: ERROR: fail to allocate the print buffer\n");
        return;
        }

    bzero (pMsgBuf, msgBufLen);
    bzero (pPrintBuf, 3*msgBufLen);
    while (logOutputDevice)
        {
        /* wait for the message */

        semTake(pMemLogDesc->wakeupId,WAIT_FOREVER);

        while (TRUE)
            {
            /* read the log buffer */

            msgLen = fwMemLogRead(pMsgBuf,msgBufLen);

            if (!msgLen)
                break;

            len = 0;

            /* interept the message code */

            if (pMsgHdr->code & FW_ACCEPT)
                {
                /* packet is accepted */

                pStr = actionStrs[ACCEPT_STR_INX];
                len += strlen(pStr);
                }
            else if (pMsgHdr->code & FW_FRAG_REASSEMBLE)
                {
                pStr = actionStrs[ASSEMBLE_STR_INX];
                len += strlen(pStr);
                }
            else if (pMsgHdr->code & FW_NEXT_RULE)
                {
                pStr = actionStrs[NEXT_RULE_STR_INX];
                len += strlen(pStr);
                }
            else if (pMsgHdr->code & FW_NEXT_RULEGROUP)
                {
                pStr = actionStrs[NEXT_GROUP_STR_INX];
                len += strlen(pStr);
                }
            else
                {
                /* packet is rejected */

                pStr = actionStrs[REJECT_STR_INX];
                len += strlen(pStr);
                }

            strcpy(tmpBuf,pStr);
            tmpBuf[len++] = ',';

            if (pMsgBuf[sizeof(MEM_LOG_MSG_HDR)] == 0)
                {
                pName = "Filter Name Not Provided";
                pData = &pMsgBuf[sizeof(MEM_LOG_MSG_HDR) + 1];
                } 
            else
                {
                pName = &pMsgBuf[sizeof(MEM_LOG_MSG_HDR)];
                pData = &pMsgBuf[sizeof(MEM_LOG_MSG_HDR) + strlen(pName) + 1];
                }

            /* safety check */

            if ((len + strlen(pName)) > (TEMP_BUF_LEN - 4))
                {
                printf("ERROR: fwLog: temporary buffer too small\n");
                free(pMsgBuf);
                free(pPrintBuf);
                return;
                }

            strcpy(tmpBuf + len, pName);
            len += strlen(pName);

            tmpBuf[len] = '.';
            tmpBuf[len+1] = ' ';
            tmpBuf[len+2] = 0;

            if (logOutputDevice == FW_LOG_TO_SYSLOG)
                {
                if (pSyslogcIfFunc)
                    {
                    (*pSyslogcIfFunc)((UINT8 *)pData,msgLen - (pData - pMsgBuf),
                                   tmpBuf, SYSLOGC_CODE_DEFAULT,0);
                    }
                else
                     printf("Logging fails, syslog client interface is not "
                            "installed\n");
                }
            else if (logOutputDevice == FW_LOG_TO_CONSOLE) /*console log*/
                {        
                printf("%s ",tmpBuf);
           
	        /* convert  the time */

	        tmpBufLen = TEMP_BUF_LEN;
	        len = asctime_r(localtime(&pMsgHdr->time),tmpBuf,&tmpBufLen);
	        tmpBuf[len - 1] =0;
	        printf("%s, ", tmpBuf);

                pktHeaderDisplay (pMsgHdr->code,(UINT8 *)pData,
                                  (UINT8 *)pMsgBuf,msgLen);

                len = binToAscStrConvert((UINT8 *)pData,
                                            msgLen - (pData - pMsgBuf),
                                            pPrintBuf,
					msgLen * 3 - 1);
                pPrintBuf[len] = 0;
                printf("Packet: %s\n",pPrintBuf);
                }
            }
        }
    free(pMsgBuf);
    free(pPrintBuf);
    }
     
                

/******************************************************************************
*
* fwLog - send to the firewall logging facility
*
* This routine is the only interface function between the firewall logging
* facility and other components. Firewall IP filter or MAC filter should always
* use this function to send a message to the logging facility. 
*
* RETURNS: N/A
*/

void fwLog
    (
    M_BLK_ID pMblk,  /* point to a mbuf containing the packet */
    UINT code,       /* action code such as FW_REJECT and FW_ACCEPT */
    FW_GROUP_ATTR * pAttr /* packet log length and user defined log ID string */
    )
    {
    struct timespec ts;

    if (pMblk == NULL)
        return;

    if (fwLogLibInitDone == FALSE)
        return;

    clock_gettime(CLOCK_REALTIME,&ts);

    fwMemLogWrite(pMblk,pAttr->logLen,code,pAttr->pGrpName,
		      ts.tv_sec);

    /* see if we need to free the mbuf */

    if (!(code & IPFWF_DONTFREE))
	netMblkClChainFree(pMblk);
    }
        
/******************************************************************************
*
* fwLogShow - display the internal logging descriptor data
*
* This routine is only used for debugging purpose only. internal usage
*
* NOMANUAL
*
*/

void fwLogShow (void)
    {
    MEM_LOG_DESC * pMem;
    DL_LIST * pList;
    MEM_LOG_NODE * pNode;
    int i = 0;

    pMem = &memLogDesc;

    printf("pMemLoc: 0x%x, wrInx: 0x%x, bufferLen: 0x%x, freeLen:0x%x\n",
            (int)pMem->pMemLoc, pMem->wrInx, pMem->bufLen,pMem->freeLen);
    printf("Number of messages have been over written: %d\n", 
	    pMem->overWrittenNum);
    printf("Number of messages have been retrieved: %d\n", 
	    pMem->retrievedNum);

    pList = &pMem->list;
    pNode = (MEM_LOG_NODE *)DLL_FIRST(pList);

    while (pNode)
        {
        printf("pMsg: 0x%x, msgLen: 0x%x, bufLen: 0x%x\n",
               (int)pNode->pMsg, pNode->len, pNode->bufLen);
        i++;
        pNode = (MEM_LOG_NODE *)DLL_NEXT(&pNode->node);
        }
    printf("The number of the messages currently in buffer: %d\n",i);
    }

/*******************************************************************************
*
* fwLogSyslogcInstall - Install the syslog client interface
*
* This routine attaches the syslog client module into the logging facility.
* Application should always call this function before using the syslog client
* functionality in the logging facility. 
*
* RETURNS: N/A
*/

void fwLogSyslogcInstall
    (
    FUNCPTR pInitFunc,     /* syslog init routine: syslogcLibInit() */
    FUNCPTR pIfFunc,       /* syslog send routine: syslogcBinDataSend() */ 
    FUNCPTR pCloseFunc     /* syslog close routine: syslogcShutdown() */
    )
    {
    pSyslogcInitFunc = pInitFunc;
    pSyslogcIfFunc   = pIfFunc;
    pSyslogcCloseFunc= pCloseFunc;
    }

/******************************************************************************
*
* binToAscStrConvert - Convert binary data to the ASCII format
*
* RETURN: number of ASCII bytes written to buffer
*/

LOCAL int binToAscStrConvert
    (
    UINT8 * pData,   /* point to a block of data */
    int     dataLen, /* data length */
    char *  pBuf,    /* buffer to store converted ASCII value */
    int     bufLen   /* length of the buffer */
    )
    {
    int i;
    int cnt = 0;
    int copyLen;

    /* make sure not write beyond the buffer limit */


    copyLen = min(dataLen, bufLen/3);

    for (i = 0; i < copyLen; i++)
        {
        /* the most significant 4 bits */

        if (BYTE_MS4BITS(pData[i]) > 9)
            pBuf[cnt++] = BYTE_MS4BITS(pData[i]) - 9 + ASCII_a;
        else
            pBuf[cnt++] = BYTE_MS4BITS(pData[i]) + ASCII_ZERO;

        /* the least significant 4 bits */

        if (BYTE_LS4BITS(pData[i]) > 9)
            pBuf[cnt++] = BYTE_LS4BITS(pData[i]) - 9 + ASCII_a;
        else
            pBuf[cnt++] = BYTE_LS4BITS(pData[i]) + ASCII_ZERO;

        /* the space char */

        pBuf[cnt++] = ' ';
        }
    return cnt;
    }

/*******************************************************************************
*
* pktHeaderDisplay - Display the packet  header
*
*/

LOCAL void pktHeaderDisplay
    (
    UINT32 code,
    UINT8 * pData,
    UINT8 * pMsgBuf,
    int  msgLen
    )
    {
    struct ip ipHdr;
    char srcIpStr[IPADDR_STR_SIZE];
    char dstIpStr[IPADDR_STR_SIZE];
    char * pProto = NULL;
    UINT16 srcPort;
    UINT16 dstPort;
    UINT8 icmpType = 0;
    UINT8 icmpCode = 0;
    UINT32 frameType = ETHERTYPE_IP;
    BOOL displayHdr = FALSE;
    int upHdrType = 0;
    int upHdrOffset = 0;
   
    /* intepret and print out some useful IP header field info */

    /* XXX borrow the flag IPFWF_MODIFY to differenciate the
     * IP packet from the ethernet packet.
     */

    if (!(code & IPFWF_MODIFY))
        {
        /* treat this is the ethernet packet */

        if ((msgLen - (pData - pMsgBuf)) >= ENET_HDR_REAL_SIZ)
            {
            printf("EthDst: %02x:%02x:%02x:%02x:%02x:%02x "
                   "src: %02x:%02x:%02x:%02x:%02x:%02x type: %04x ",
                   pData[0],pData[1],pData[2],pData[3],pData[4],pData[5],
                   pData[6],pData[7],pData[8],pData[9],pData[10],pData[11],
                   (pData[12] << 8) | pData[13]);
            frameType = (pData[12] << 8) | pData[13];
            pData += ENET_HDR_REAL_SIZ;
            }
        }

    if ( ((pData[0] & IP_VERSION_MASK) == IPV4_VERSION) &&
         ((msgLen - (pData - pMsgBuf)) >= sizeof(struct ip)) &&
        (frameType == ETHERTYPE_IP) )
        {
        bcopy((char *)pData,(char *)&ipHdr,sizeof(ipHdr));
        inet_ntoa_b(ipHdr.ip_src,srcIpStr);
        inet_ntoa_b(ipHdr.ip_dst,dstIpStr);
        displayHdr = TRUE;
        upHdrType = ipHdr.ip_p;
        upHdrOffset = ipHdr.ip_hl << 2;
        }
#ifdef INET6
    else if ( ((pData[0] & IP_VERSION_MASK) == IPV6_VERSION) &&
              ((msgLen - (pData - pMsgBuf)) >= sizeof(struct ip6_hdr)) )
        {
        struct ip6_hdr * pIpv6;
        pIpv6 = (struct ip6_hdr *)pData;

        inet_ntop (AF_INET6, (void *)pIpv6->ip6_src.s6_addr,srcIpStr,
			    INET6_ADDRSTRLEN);
        inet_ntop (AF_INET6, (void *)pIpv6->ip6_dst.s6_addr,dstIpStr,
			    INET6_ADDRSTRLEN);

        if (ipv6UpHdrOffsetGet(pIpv6,&upHdrType, &upHdrOffset,
                 msgLen - (pData - pMsgBuf)) == TRUE)
            displayHdr = TRUE;
        }
#endif

    if (displayHdr == TRUE)
        { 
        switch (upHdrType)
            {
            case IPPROTO_TCP:
                pProto = "TCP";
            case IPPROTO_UDP:
                if (upHdrType == IPPROTO_UDP)
                    pProto = "UDP";

                bcopy((char *)(pData + upHdrOffset),
                      (char *)&srcPort,2);
                bcopy((char *)(pData + upHdrOffset + 2),
                      (char *)&dstPort,2);
                srcPort=ntohs(srcPort);
                dstPort=ntohs(dstPort);
                break;

            case IPPROTO_ICMP:
                pProto = "ICMP";
            case IPPROTO_ICMPV6:
                if (upHdrType == IPPROTO_ICMPV6)
                    pProto = "ICMPV6";
                icmpType = (pData + upHdrOffset)[0];
                icmpCode = (pData + upHdrOffset)[1];
                break;
            default:
		break;
            }
        printf("IPsrcAddr: %s, dstAddr: %s, ",srcIpStr,dstIpStr);
        if (pProto)
            printf("proto: %s, ",pProto);
        else
            printf("proto: %d, ",upHdrType);

        if (upHdrType == IPPROTO_ICMP || upHdrType == IPPROTO_ICMPV6)
            printf("type: %d, code: %d, ",icmpType,icmpCode);
        else if (upHdrType == IPPROTO_UDP ||
                 upHdrType == IPPROTO_TCP)
            printf("srcPort: %d, dstPort: %d, ",
                    srcPort,dstPort);
        else
            printf(", ");
        }
   }