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


/* fwUtilLib.c - Firewall Utility Module  */

/* Copyright 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
--------------------
01n,16mar06,kch  Modified fwRuleShow() to display ALTQ output as the last
                 entry for the rules group. Also modified fwStatsShow() to 
                 display the hook location string.
01m,01mar06,kch  Added ALTQ support to fwRulesShow().
01l,25aug05,zhu  added per host rate limiting show routine
01k,13dec04,myz  added IPV6 support
01j,13jul04,myz  port to dual stack
01i,08mar04,myz  improved the field diplay of fwRulesShow.
01h,27feb04,myz  moved in three routines from fwRuleLib.c and fwLogLib.c
01g,18feb04,myz  obsolete 5 web interface functions.
01f,11feb04,myz  added fwRuleIdGet function
01e,09feb04,myz  modified for fwRuleGroupCreate change and other improvements.
01c,30jan04,myz  public API name changes
01b,29jan04,myz  modified for the change of FW_RULE_ENTRY
01a,15oct03,myz  written
*/

/*
DESCRIPTION

This library provides a collection of utility functions for rule filter and
logging facilities.  User can use the show routines contained in this module
to display the information related to the rule filter. User can also use 
either of the two time functions to set up the target clock. For time of day
rule field and the logging facility, the target clock should be initialized 
first. 

*/

#include "fw.h"
#include "envLib.h"
#include "sntpcLib.h"

#define VALUE_ADDR_TYPE 1
#define VALUE_INT32_TYPE  2
#define VALUE_INT16_TYPE  3
#define VALUE_INT8_TYPE  4
#define VALUE_IPADDR_TYPE 5
#define DEFAULT_TIMEZONE "TIMEZONE=PDT::480:040102:102802"

/* external functions */
#ifdef ALTQ
IMPORT int pf_qid2qname(u_int32_t qid, char *p);
#endif /* ALTQ */

int fwUtilShowDebug = 0;

LOCAL char * opStr[] = {"NONE","AND_OP","OR_OP"};
LOCAL char * hdrOpStr[] = {"EQ_OP","LT_OP","GT_OP","INVALID"};

LOCAL char * dayStr[] = {"SUN","MON","TUE","WED","THU","FRI","SAT"};
LOCAL char notUsedStr[] = "N/A";

LOCAL char *locStr[] = {
    "PRE-INPUT", "INPUT", "FORWARD", "OUTPUT",
#ifdef INET6
    "PRE-INPUT6", "INPUT6", "FORWARD6", "OUTPUT6",
#endif /* INET6 */
    };
    
/******************************************************************************
*
* fwRulesShow - Display the rule list  
*
* This routine displays one of the four rule lists at a time. The list is 
* selected by the parameter locType.
*
* RETURNS: OK, or ERROR if a invalid parameter
*/

int fwRulesShow
    (
    FW_LOC_TYPE locType   /* one of the four installation location */
    )
    {
    LIST * pList;
    FW_RULE_ENTRY * pEntry;
    FW_GROUP_HEAD_ENTRY * pHead;
    FW_RULE_ENTRY_NODE * pEntryNode;
    FW_RULE_ENTRY_NODE * pFirstNode;
    int i = 0;
    int prevProto;
    int curProto;
    int proto;
    FW_RULE_PKTSIZE pktSize;
    struct in_addr ipAddr;
    char addrStr[100];
    char addrStr1[100];
    char * pTmpName;

    if (locType >= FW_END_LOC)
        {
        printf("ERROR: Wrong type\n");
        return ERROR;
        }

    if ((pList = fwRuleListGet(locType)) == NULL)
	return ERROR;

    pHead = (FW_GROUP_HEAD_ENTRY *)lstFirst(pList);

    while (pHead)
        {

        printf("\n-- Rule Group %d ID: 0x%x Name: %s --\n\n", ++i,
               (int)pHead->attr.groupId,
	       pHead->attr.pGrpName? pHead->attr.pGrpName: "NONE");

	prevProto = 0;
        pEntryNode = (FW_RULE_ENTRY_NODE *)lstFirst(&pHead->ruleList);
        pFirstNode = pEntryNode;

        while (pEntryNode)
            {
            pEntry = &pEntryNode->rule;

	    addrStr[0] = 0;

	    if ((pEntryNode != pFirstNode) || (lstCount(&pHead->ruleList) == 1))
                {
                if (lstCount(&pHead->ruleList) > 1)
                    printf("ruleId: 0x%x  ",(int)pEntryNode);

                if (pEntry->actions & FW_ACCEPT)
                    strcpy(addrStr,"ACCEPT,");
                else if (pEntry->actions & FW_USER_ACTION)
                    strcpy(addrStr,"USER ACTION,");
                else if (pEntry->actions & FW_NEXT_RULE)
                    strcpy(addrStr,"NEXT RULE,");
                else if (pEntry->actions & FW_NEXT_RULEGROUP)
                    strcpy(addrStr,"NEXT GROUP,");
                else if (pEntry->actions & FW_FRAG_REASSEMBLE)
                    strcpy(addrStr,"REASSEMBLE,");
                else
                    {

                    if (pEntry->actions & FW_TCP_RESET)
                        {
                        strcpy(addrStr,"TCP_RESET,");
                        }
                    else if (pEntry->actions & FW_ICMP)
                        {
                        strcpy(addrStr,"ICMP,");
                        }
 
                    strcpy(addrStr + strlen(addrStr),"REJECT,");
                    }

                if (pEntry->actions & FW_LOG)
                    strcpy(addrStr+strlen(addrStr),"LOG ");
                }
            else
                strcpy(addrStr,"N/A");
      
            printf("Actions: %s ",addrStr);

            /* interface name unit */

            if (pEntry->srcIf.name[0] != 0)
                printf("SrcIf: %s%d ", pEntry->srcIf.name,pEntry->srcIf.unit);
            else
                printf("SrcIf: %s ",notUsedStr);

            if (pEntry->dstIf.name[0] != 0)
                printf("DstIf: %s%d\n", pEntry->dstIf.name,pEntry->dstIf.unit);
            else
                printf("DstIf: %s\n",notUsedStr);

            /* IP source start and end addresses */

#ifdef INET6
            if (pHead->attr.type & FW_RULE_TYPE_IPV6)
                {
		if ((!V6ADDR32_IS_ASSIGNED(pEntry->srcStartV6Addr32)) &&
		    (!V6ADDR32_IS_ASSIGNED(pEntry->srcEndV6Addr32)) )
                    printf("SrcAddr: %s ",notUsedStr);
                else
                    {
                    inet_ntop (AF_INET6, (void *)pEntry->srcStartV6Addr8,
                               addrStr,INET6_ADDRSTRLEN);
                    inet_ntop (AF_INET6, (void *)pEntry->srcEndV6Addr8,
                               addrStr1,INET6_ADDRSTRLEN);

                    printf("SrcAddr: %s/%s\n",addrStr,addrStr1);
                    }

                /* IP destination start and end addresses */


		if ((!V6ADDR32_IS_ASSIGNED(pEntry->dstStartV6Addr32)) &&
		    (!V6ADDR32_IS_ASSIGNED(pEntry->dstEndV6Addr32)) )
                    printf("DstAddr: %s\n",notUsedStr);
                else
                    {
                    inet_ntop (AF_INET6, (void *)pEntry->dstStartV6Addr32,
                               addrStr,INET6_ADDRSTRLEN);
                    inet_ntop (AF_INET6, (void *)pEntry->dstEndV6Addr32,
                               addrStr1,INET6_ADDRSTRLEN);

                    printf("DstAddr: %s/%s\n",addrStr,addrStr1);
                    }
                }
            else /* V4 */
#endif
                {
                if (pEntry->srcStartV4Addr == 0 && pEntry->srcEndV4Addr == 0)
                    printf("SrcAddr: %s ",notUsedStr);
                else
                    {
                    ipAddr.s_addr = htonl(pEntry->srcStartV4Addr);
                    inet_ntoa_b(ipAddr,addrStr);
                    ipAddr.s_addr = htonl(pEntry->srcEndV4Addr);
                    inet_ntoa_b(ipAddr,addrStr1);
                    printf("SrcAddr: %s/%s ",addrStr,addrStr1);
                    }

                /* IP destination start and end addresses */

                if (pEntry->dstStartV4Addr == 0 &&
                    pEntry->dstEndV4Addr   == 0)
                    printf("DstAddr: %s\n",notUsedStr);
                else
                    {

                    printf("DstAddr: ");
                    ipAddr.s_addr = htonl(pEntry->dstStartV4Addr);
                    inet_ntoa_b(ipAddr,addrStr);
                    ipAddr.s_addr = htonl(pEntry->dstEndV4Addr);
                    inet_ntoa_b(ipAddr,addrStr1);
                    printf("%s/%s\n",addrStr, addrStr1);
                    }
                }

#if INET6
            if (pHead->attr.type & FW_RULE_TYPE_IPV6)
                {
                char * pOpStr;

                strcpy(addrStr,"fLabel: ");
                if (!pEntry->fLabelV6.start && !pEntry->fLabelV6.end)
                    strcpy(addrStr + strlen(addrStr),notUsedStr);
                else
                    sprintf(addrStr+strlen(addrStr),"%d/%d",
                            pEntry->fLabelV6.start, pEntry->fLabelV6.end);
 	        printf("%s ",addrStr);

                strcpy(addrStr,"EXTHdrs: ");
                if (pEntry->extListV6.opType == FW_AND_OP)
                    pOpStr = "AND_OP";
                else if (pEntry->extListV6.opType == FW_OR_OP)
                    pOpStr = "OR_OP";
                else if (pEntry->extListV6.opType == FW_EXACT_OP)
                    pOpStr = "EXACT_OP";
                else if (pEntry->extListV6.opType == FW_RANGE_OP)
                    pOpStr = "LIMIT_OP";
                else 
                    pOpStr = notUsedStr;

                strcpy(addrStr + strlen(addrStr),pOpStr);
                if (pOpStr != notUsedStr)
                    {
                    if (pEntry->extListV6.opType == FW_RANGE_OP)
                        sprintf(addrStr+strlen(addrStr),",%d/%d ",
                                pEntry->extRangeV6.start,
                                pEntry->extRangeV6.end);
                    else
                        sprintf(addrStr+strlen(addrStr),",%d,%d,%d,%d,%d,%d ",
                            pEntry->extHdrV6.num,pEntry->extHdrV6.types[0],
                            pEntry->extHdrV6.types[1], 
                            pEntry->extHdrV6.types[2], 
                            pEntry->extHdrV6.types[3], 
                            pEntry->extHdrV6.types[4]); 
                    }
                printf("%s ",addrStr);
                }
#endif                
                

#ifdef INET6
            if (pHead->attr.type & FW_RULE_TYPE_IPV6)
                proto = pEntry->protoV6;
            else 
#endif
                proto = pEntry->protoV4;
        
            /* protocol, header len and option */

            if (proto == IPPROTO_TCP)
                {
                prevProto = IPPROTO_TCP;
                strcpy(addrStr,"TCP");
                }
            else if (proto == IPPROTO_UDP)
                {
                prevProto = IPPROTO_UDP;
                strcpy(addrStr,"UDP");
                }
            else if (proto == IPPROTO_ICMP)
                {
                prevProto = IPPROTO_ICMP;
                strcpy(addrStr,"ICMP");
                }
            else if (proto == IPPROTO_ICMPV6)
                {
                prevProto = IPPROTO_ICMPV6;
                strcpy(addrStr,"ICMPV6");
                }
         
            else if (proto)
                sprintf(addrStr,"%d",proto);
            else
                strcpy(addrStr,notUsedStr);

            printf("Proto: %s ",addrStr);

            if (pHead->attr.type & FW_RULE_TYPE_IPV4)
                {
                if (pEntry->hdrLenV4)
                    sprintf(addrStr,"%d-%s",(pEntry->hdrLenV4) & (~0x3),
                        hdrOpStr[(pEntry->hdrLenV4) & 0x3]);
                else
                    strcpy(addrStr,notUsedStr);
 
                printf("HdrLen(len-op): %s ", addrStr);
                }
               
            /* fragment and packet size and state */

#ifdef INET6
            if (pHead->attr.type & FW_RULE_TYPE_IPV6)
                pktSize = pEntry->pktSizeV6;
            else
#endif
                pktSize = pEntry->pktSizeV4;

            if (pktSize.start == 0 && pktSize.end == 0)
                strcpy(addrStr,notUsedStr);
            else
                sprintf(addrStr,"%d/%d",pktSize.start,
                                        pktSize.end);

#ifdef INET6
            if (pHead->attr.type & FW_RULE_TYPE_IPV6)
                printf("PktSize: %s\n",addrStr);
            else		 
#endif
                printf("PktSize: %s ",addrStr);

            if (pHead->attr.type & FW_RULE_TYPE_IPV4)
                {
                if (pEntry->fragV4 == 0)
                    strcpy(addrStr,notUsedStr);
                else
                    strcpy(addrStr,"TRUE"); 
                printf("FragOption: %s\n",addrStr);
                }
          
            /* transport header */

            curProto = proto? proto: prevProto;

            if ((curProto == IPPROTO_TCP || curProto == IPPROTO_UDP))
                {
                UINT16 sports;
                UINT16 sporte;
                UINT16 dports;
                UINT16 dporte;

                if (curProto == IPPROTO_TCP)
                    {
                    sports = pEntry->tport.tcp.srcPort.start;
                    sporte = pEntry->tport.tcp.srcPort.end;
                    dports = pEntry->tport.tcp.dstPort.start;
                    dporte = pEntry->tport.tcp.dstPort.end;
                    }
                else
                    {
                    sports = pEntry->tport.udp.srcPort.start;
                    sporte = pEntry->tport.udp.srcPort.end;
                    dports = pEntry->tport.udp.dstPort.start;
                    dporte = pEntry->tport.udp.dstPort.end;
                    }
                if (sports == 0 && sporte == 0)
                    strcpy(addrStr,notUsedStr);
                else
                    sprintf(addrStr,"%d/%d",sports,sporte);
                printf("SrcPort: %s ",addrStr);                    

                if (dports == 0 && dporte == 0)
                    strcpy(addrStr,notUsedStr);
                else
                    sprintf(addrStr,"%d/%d",dports,dporte);
                printf("DstPort: %s ",addrStr);                    

                if (curProto == IPPROTO_TCP)
                    {
                    if (pEntry->tport.tcp.tcpFlag.operation == 0)
                        strcpy(addrStr,notUsedStr);
                    else
                        sprintf(addrStr,"0x%x-0x%x-%s",
                                pEntry->tport.tcp.tcpFlag.flag,
                                pEntry->tport.tcp.tcpFlag.mask,
                                opStr[pEntry->tport.tcp.tcpFlag.operation]);
                    printf(" TCPFlag(flag-mask-op): %s\n",addrStr);
                    }
                else
                    printf("\n");
                }
            else if (curProto == IPPROTO_ICMP || curProto == IPPROTO_ICMPV6)
                {
                if (pEntry->tport.icmp.type == FW_INVALID_ICMP_TYPE)
                    printf("ICMP type: %s Code: %s\n",notUsedStr,notUsedStr);
                else
                    printf("ICMP type: %d Code: %d\n",
		       pEntry->tport.icmp.type,pEntry->tport.icmp.code);
                }

            /* the time of day */

	    addrStr[0] = 0;
            if (pEntry->timeOfDay.days & FW_DAY_ALL)
                {
                int shour;
                int sminute;
                int ssecond;
                int ehour;
                int eminute;
                int esecond;

                if ((pEntry->timeOfDay.days & FW_DAY_ALL) == FW_DAY_ALL)
                    strcpy(addrStr,"Whole week");
                else
                    {
                    int i;
                    int strLen;

                    if (pEntry->timeOfDay.days)
                        {
                        for (i = 0; i < 7; i++)
                            {
                            if (pEntry->timeOfDay.days & (1 << i) )
				{
                                strcpy(addrStr + strlen(addrStr),dayStr[i]);
                                strLen = strlen(addrStr);
                                addrStr[strLen] = ',';
                                addrStr[strLen + 1] = 0;
				}
                            }
                        if (strlen(addrStr))
                            addrStr[strlen(addrStr) - 1] = 0;
                        }
                    }
                if (pEntry->timeOfDay.secStart == 0 &&
                    pEntry->timeOfDay.secEnd   == 0)
                    printf("Day: %s Time: %s ",addrStr,notUsedStr);
                else
                    {
                    shour = pEntry->timeOfDay.secStart / 3600;
                    sminute = (pEntry->timeOfDay.secStart % 3600) / 60;
                    ssecond = (pEntry->timeOfDay.secStart % 3600) % 60;
                    ehour = pEntry->timeOfDay.secEnd / 3600;
                    eminute = (pEntry->timeOfDay.secEnd % 3600) / 60;
                    esecond = (pEntry->timeOfDay.secEnd % 3600) % 60;
   
                    printf("Day: %s Time: %02d:%02d:%02d-%02d:%02d:%02d ",
                            addrStr, shour,sminute,ssecond,
                            ehour,eminute,esecond);
                    }
                }
            else /* no timeOfDay rule field */
                printf("TimeOfDay: %s ",notUsedStr);             
   
	    pTmpName = 0;
            addrStr[0] = 0;
            if (pEntry->connTrack.entity)
                {
                if (pEntry->connTrack.entity == FW_CONN_INITIATOR)
                    pTmpName = "INITIATOR";
                else if (pEntry->connTrack.entity == FW_CONN_RESPONDER)
                    pTmpName = "RESPONDER";

                if (pEntry->connTrack.state & FW_CONN_STATE_CREATE)
                    strcpy(addrStr,"CREATE,");
                if (pEntry->connTrack.state & FW_CONN_STATE_NEW)
                    strcpy(addrStr + strlen(addrStr),"NEW,");
                if (pEntry->connTrack.state & FW_CONN_STATE_ESTABLISHED)
                    strcpy(addrStr + strlen(addrStr),"ESTABLISHED");
                }
 
	    if (!pEntry->connTrack.entity)
                printf("State: %s", notUsedStr);
            else if (pTmpName)		
                printf("State: %s-%s", pTmpName, addrStr);

            addrStr[0] = 0;
            if (pEntry->rateLimit.op)
                {
                addrStr1[0]=0;                
                if (pEntry->rateLimit.op == FW_GT_OP)
                    strcpy(addrStr,"GT_OP,");
                else if (pEntry->rateLimit.op == FW_LT_OP)
                    strcpy(addrStr,"LT_OP,");
                if (pEntry->rateLimit.trkSltor == FW_ALL_TRK_OFF)
                    strcpy(addrStr1,"HOST TRACK OFF");
                else if (pEntry->rateLimit.trkSltor == FW_SRC_TRK_ON)
                    strcpy(addrStr1,"SRC TRACK ON");
                else if (pEntry->rateLimit.trkSltor == FW_DST_TRK_ON)
                    strcpy(addrStr1,"DST TRACK ON");

                sprintf(addrStr+strlen(addrStr),"%d,%d,%s,%d",
                         pEntry->rateLimit.limit,pEntry->rateLimit.duration,
                         addrStr1, 
                         pEntry->rateLimit.trkSltor == FW_ALL_TRK_OFF ? 
                         0 : pEntry->rateLimit.trkMax);
                }

            if (!pEntry->rateLimit.op)
                printf(" RateLimit: %s\n", notUsedStr);
            else 		
                printf(" RateLimit: %s\n", addrStr);
                
            if (fwUtilShowDebug)
                printf("fieldsFlag: 0x%x\n",pEntryNode->fieldsFlag);

#ifdef ALTQ
            if (pEntry->qid != 0)
                {
                char qname[16];
                bzero(qname, sizeof(qname));
                printf("Altq queue name: %s\n", 
                       pf_qid2qname(pEntry->qid, qname) == 0 ? qname : "N/A");
                }
#endif /* ALTQ */

            printf("\n");

            pEntryNode = (FW_RULE_ENTRY_NODE *)lstNext((NODE *)pEntryNode);
            }
        pHead = (FW_GROUP_HEAD_ENTRY *)lstNext((NODE *)pHead);
        }
    return OK;
    }

/*******************************************************************************
*
* fwStatsShow - display the various statistic counters 
*
* This routine displays the various statistic counters associated with the 
* given install location. The parameter locType selects which install
* location.
*
* RETURNS: N/A
*/

void fwStatsShow
    (
    FW_LOC_TYPE locType   /* which install location */
    )
    {
    RULE_FILTER_STAT_DESC * pStats = NULL;
    RULE_LIST_DESC * pDesc = NULL;

    if ((UINT32)locType >= FW_END_LOC)
        {
        printf("ERROR: Wrong type\n");
        return;
        }

    pDesc = fwListDescGet(locType);
    pStats = &pDesc->stats;

    printf("%s: ", locStr[locType]);
    printf("dropped: %d, accepted: %d, reported: %d\n",
           (int)pStats->dropped, (int)pStats->accepted, (int)pStats->reported);
    }
/*******************************************************************************
*
* fwInstallShow - display IP rule filter installation status
*
* This routine displays status of the four rule filter install locations. 
* It displays whether it is installed and what the default action is.
*
* RETURNS: N/A
*
*/

void fwInstallShow (void)
    {
    int name[4];
    ipfw_filter_t fltDesc;
    int fltLen;
    RULE_LIST_DESC * pDesc = NULL;
    int installedCnt = 0;
    int i;
    struct {
	int fltLoc;
	char * pLocStr;
	} locInfo[FW_END_LOC] = {
		    {IPFW_PREINPUT,"PRE-INPUT"},
		    {IPFW_INPUT,   "INPUT"},
		    {IPFW_FORWARD, "FORWARD"},
		    {IPFW_OUTPUT,  "OUTPUT"},
#ifdef INET6
		    {IPFW_PREINPUT6,"PRE-INPUT6"},
		    {IPFW_INPUT6,   "INPUT6"},
		    {IPFW_FORWARD6, "FORWARD6"},
		    {IPFW_OUTPUT6,  "OUTPUT6"}
#endif
		    };

    for (i = 0; i < FW_END_LOC; i++)
	{
        pDesc = fwListDescGet(i);
        fltLen = sizeof(ipfw_filter_t);
        bzero((char *)&fltDesc,fltLen);
        name[0] = locInfo[i].fltLoc;
        name[1] = IPFWCTL_LIST;
        name[2] = FW_RULE_FILTER;
        name[3] = pDesc->serialNo;

        ipfwSysctl(name,4,(void *)&fltDesc,(void *)&fltLen,NULL,0);

        if (fltDesc.serial)
            {
            installedCnt++;
            printf("Installed at %s location, Default Action: %s",
		  locInfo[i].pLocStr,
                  (UINT32)(pDesc->attr.groupId) & FW_ACCEPT? "ACCEPT":"REJECT");
            if ((UINT32)(pDesc->attr.groupId) & FW_LOG)
                printf(",LOG");
            printf("\n");
            }
        }

    if (!installedCnt)
        printf("Firewall IP Filter is NOT installed at any location!!!\n");
    }

/*******************************************************************************
*
* fwClockBaseInit - manually initialize the target clock
*
* This routine initializes the target clock with the given values. 
*
* RETURNS: OK or ERROR
*/

STATUS fwClockBaseInit
    (
    UINT32 year,    /* for example 2004 */
    UINT32 month,   /* 1 - 12 */
    UINT32 day,     /* 1 - 31 */
    UINT32 hour,    /* 0 - 23 */
    UINT32 minutes, /* 0 - 59 */
    UINT32 seconds  /* 0 - 59 */
    )
    {
    struct tm inputTime;
    struct timespec calTime;

    inputTime.tm_sec = seconds;
    inputTime.tm_min = minutes;
    inputTime.tm_hour = hour;
    inputTime.tm_mday = day;
    inputTime.tm_mon  = month - 1;
    inputTime.tm_year = year - 1900;

    calTime.tv_sec = mktime(&inputTime);
    calTime.tv_nsec = 0;

    return clock_settime(CLOCK_REALTIME,&calTime);
    }

/******************************************************************************
*
* ntpTimeGet - Retrieve the time from NTP time server.
*
* RETURNS: N/A
*
*/
LOCAL void ntpTimeGet
    (
    char * pTimeServer
    )
    {
    int i;
    struct timespec baseTime;

    for (i = 10; i > 0; i--)
        {
        /* try a few more time if not successful */

        if (sntpcTimeGet(pTimeServer,
                            sysClkRateGet() * (3 * (10 - i) + 1),
                            &baseTime) == OK)
            {
            clock_settime(CLOCK_REALTIME,&baseTime);

            /* need to have correct time zone setup in order to have the valid
             * local time.
             */

            if (getenv("TIMEZONE") == NULL)
                putenv(DEFAULT_TIMEZONE);

            break;
            }
        }
    }

/******************************************************************************
*
* fwClockTimeSet - set the clock with time retrieved from NTP time server
*
* This routine will retrieve the current time from a NTP time server if
* it can reaches the time server. It then sets the target clock accordingly.
* 
* RETURNS: N/A
*/

void fwClockTimeSet
    (
    char * ntpServerAddrStr  /* The IP address of the NTP timer server */
    )
    {
    taskSpawn("tNtpTimeGet", 200, 0, 10 * 1024, (FUNCPTR)ntpTimeGet,
                      (int)ntpServerAddrStr,2,3,4,5,6,7,8,9,10);
    }

/*******************************************************************************
*
* fwTrkTblShow - Display a given rule's track tables.
*
* RETURNS: OK, or ERROR if a invalid parameter
* 
* NOMANUAL
*/
                      
STATUS fwTrkTblShow
    (
    void * id       /* groupId for head rule, otherwise ruleId */
    )
    {
    FW_GROUP_HEAD_ENTRY * pHeadRule;
    FW_RULE_ENTRY_NODE * pRuleNode;
    FW_RULE_ENTRY * pRuleEntry;
    UINT8 type;
    UINT16 i;
    UINT16 cnt = 0;
    FW_IP_TRK_ENTRY * pTbl;
#ifdef INET6
    FW_IPV6_TRK_ENTRY * pV6Tbl;
#endif    
    UINT32 curTick;
    UINT32 tickDiff;
    UINT32 duration;
    
    if (!id)
        {
        printf ("Error: No rule ID \n");
        return ERROR;
        }

    if (fwIpfIdVerify(id,FW_GROUP_ID_TYPE))
        {
        /* this is the groupId */

        pHeadRule = (FW_GROUP_HEAD_ENTRY *)id;

        pRuleNode = &pHeadRule->ruleEntry;
        }
    else
        {
        /* not group ID, check if a valid rule ID */

        if (fwIpfIdVerify(id,FW_RULE_ID_TYPE))    
            pRuleNode = (FW_RULE_ENTRY_NODE *)id;
        else
            {
            /* not a valid ID */
            printf("fwTrkTblShow: Invalid ID\n");
            return ERROR;
            }
        pHeadRule = (FW_GROUP_HEAD_ENTRY *)pRuleNode->ownerId;
        }
        
        pRuleEntry = &pRuleNode->rule;
        
        if (pRuleEntry->rateLimit.op)
            {
            curTick = tickGet();
            duration = pRuleEntry->rateLimit.duration * sysClkRateGet();
            if (pRuleEntry->rateLimit.trkSltor != FW_ALL_TRK_OFF)
                {
                printf ("%s host tracking table size %d:\n",
                    pRuleEntry->rateLimit.trkSltor == FW_SRC_TRK_ON ?
                    "Source":"Destination", pRuleEntry->rateLimit.trkMax);                
#ifdef INET6
                if (pHeadRule->attr.type & FW_RULE_TYPE_IPV6)
                    {
                    pV6Tbl = (FW_IPV6_TRK_ENTRY *)pRuleEntry->
                               rateLimit.pTrkTbl;

                    for (i=0; i< pRuleEntry->rateLimit.trkMax; i++)
                        {
                        if (pV6Tbl[i].ipV6Addr.s6_addr32[0] || 
                            pV6Tbl[i].ipV6Addr.s6_addr32[1] ||
                            pV6Tbl[i].ipV6Addr.s6_addr32[2] ||
                            pV6Tbl[i].ipV6Addr.s6_addr32[3] )
                            {
                            if ((curTick - pV6Tbl[i].startTick) < 0)
                                {
                                /* tick counter has wrapped around */
                                tickDiff = curTick + ((UINT32)0xFFFFFFFF 
                                           - pV6Tbl[i].startTick);
                                } 
                            else
                                tickDiff = curTick - pV6Tbl[i].startTick;
                                
                            printf("Entry %d: %x:%x:%x:%x Count: %d " 
                                    "%s, startTick %d, diff %d\n", i, 
                                   pV6Tbl[i].ipV6Addr.s6_addr32[0],
                                   pV6Tbl[i].ipV6Addr.s6_addr32[1],
                                   pV6Tbl[i].ipV6Addr.s6_addr32[2],
                                   pV6Tbl[i].ipV6Addr.s6_addr32[3], 
                                   pV6Tbl[i].intPktNum,
                                   (tickDiff >= duration) ? "Expired":"Valid",
                                   pV6Tbl[i].startTick, tickDiff);
                                   
                            if (tickDiff < duration)
                                cnt++;         
                            }
                        }
                    if (pV6Tbl[i].intPktNum)
                        { /*overflow*/
                        if ((curTick - pV6Tbl[i].startTick) < 0)
                            {
                            /* tick counter has wrapped around */
                            tickDiff = curTick + ((UINT32)0xFFFFFFFF 
                                       - pV6Tbl[i].startTick);
                            } 
                        else
                            tickDiff = curTick - pV6Tbl[i].startTick;
                                                    
                        printf("Overflowed! Count: %d %s, startTick %d, "
                               "diff %d\n", pV6Tbl[i].intPktNum,
                                   (tickDiff >= duration) ? "Expired":"Valid",
                                   pV6Tbl[i].startTick, tickDiff);
                        }                        
                    
                    }
                else
#endif              /* IPv4 */  
                    {
                    pTbl = (FW_IP_TRK_ENTRY *)pRuleEntry->rateLimit.pTrkTbl;

                    for (i=0; i< pRuleEntry->rateLimit.trkMax; i++)
                        {
                        if (pTbl[i].ipAddr.s_addr)
                            {
                            if ((curTick - pTbl[i].startTick) < 0)
                                {
                                /* tick counter has wrapped around */
                                tickDiff = curTick + ((UINT32)0xFFFFFFFF 
                                           - pTbl[i].startTick);
                                } 
                            else
                                tickDiff = curTick - pTbl[i].startTick;
                                                            
                            printf("Entry %d: 0x%x Count: %d %s, "
                                   "startTick %d, diff %d\n", i, 
                                   pTbl[i].ipAddr.s_addr, 
                                   pTbl[i].intPktNum,
                                   (tickDiff >= duration) ? "Expired":"Valid",
                                   pTbl[i].startTick, tickDiff);
                                   
                            if (tickDiff < duration)
                                cnt++;       
                            }
                        }
                    if (pTbl[i].intPktNum)
                        { /*overflow*/
                        if ((curTick - pTbl[i].startTick) < 0)
                            {
                            /* tick counter has wrapped around */
                            tickDiff = curTick + ((UINT32)0xFFFFFFFF 
                                       - pTbl[i].startTick);
                            } 
                        else
                            tickDiff = curTick - pTbl[i].startTick;
                                                        
                        printf("Overflowed! Count: %d %s, startTick %d, "
                               "diff %d\n", pTbl[i].intPktNum,
                                   (tickDiff >= duration) ? "Expired":"Valid",
                                   pTbl[i].startTick, tickDiff);
                        }                       
                    }    
                printf ("Total Used Entries: %d, Available: %d \n\n", cnt, 
                    pRuleEntry->rateLimit.trkMax - cnt);
                }

            }
    return OK;         
    }