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


/* fwNvRuleLib.c - firewall rule non-volatile storage interface 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
--------------------
01k,03mar06,kch  Fixed coverity issues in nvRuleDataSet(), ruleGrpNvFmtCvt()
                 (SPR#118475).
01j,10mar05,svk  Fix compilation warning
01i,13dec04,myz  added IPV6 support
01h,13jul04,myz  move common header files to fw.h
01g,27may04,svk  Add comment about using target server file system
01f,05mar04,myz  fixed the problem of losing ICMP default value
01e,09feb04,myz  modified for fwRuleGroupCreate function change
01c,30jan04,myz  public API name changes
01b,29jan04,myz  Modified for the change of FW_GROUP_ATTR and FW_RULE_ENTRY 
01a,16dec03,myz  written.
*/

/*
DESCRIPTION

This library provides facilities to save/restore the IP Firewall rule lists 
to/from the Non-volatile(NV) storage.  It accesses the NV storage through the
Firewall common NV interface functions(fwNvParamsSet/fwNvParamsGet). User needs
to populate this interface with its hardware specific routines by calling the
fwNvFuncsInstall().  

The format of the rule list stored in the NV storage is different from the
format kept in the RAM for the purpose of minimizing NV storage space usage. 
The NV storage format is described by structure NV_RULE_LIST_TBL in this file.

*/

#include "fw.h"

/* Local defines */

/* rule field usage indication bits */

#define NV_RULE_SRCIF_BIT    (0x1 << 0)
#define NV_RULE_DSTIF_BIT    (0x1 << 1)
#define NV_RULE_SRCADR_BIT   (0x1 << 2)
#define NV_RULE_DSTADR_BIT   (0x1 << 3)
#define NV_RULE_HDRLEN_BIT   (0x1 << 4)
#define NV_RULE_PROTO_BIT    (0x1 << 5)
#define NV_RULE_OPTION_BIT   (0x1 << 6)
#define NV_RULE_FRAG_BIT     (0x1 << 7)
#define NV_RULE_PKTSIZE_BIT  (0x1 << 8)

/* next three bits reserved for transport layer header */

/* TCP */

#define NV_RULE_TCPSPORT_BIT (0x1 << 9)
#define NV_RULE_TCPDPORT_BIT (0x1 << 10)
#define NV_RULE_TCPFLAG_BIT  (0x1 << 11)

/* UDP */

#define NV_RULE_UDPSPORT_BIT (0x1 << 9)
#define NV_RULE_UDPDPORT_BIT (0x1 << 10)

/* ICMP */

#define NV_RULE_ICMPTYPE_BIT (0x1 << 9)

#define NV_RULE_TIMEDAY_BIT  (0x1 << 12)
#define NV_RULE_STATE_BIT    (0x1 << 13)
#define NV_RULE_EXTHDRS_BIT  (0x1 << 14)
#define NV_RULE_FLOWLABEL_BIT (0x1 << 16)

#define NV_RULE_IF_ENABLE    1
#define NV_RULE_IF_DISABLE   2 

#define NUMOFGROUP_FIELD_SIZE     4
#define PKTSIZE_FIELD_SIZE        sizeof(FW_RULE_PKTSIZE)
#define PKTPORTS_FIELD_SIZE       sizeof(FW_RULE_PORT)

#ifdef INET6
#define FLOWLABEL_FIELD_SIZE      sizeof(FW_RULE_V6LABEL)
#endif

/* typedefs */

/* rule group Non-volatile storage format */

typedef struct {
    UINT32 grpLen;   /* the group total length including this field */
    UINT16 logLen;
    UINT8  ruleNum;  /* number of rules in this group including head rule */
    UINT8  nameLen;  /* length of group name including 0 terminator */
    /* variable group name follows */
    } _WRS_PACK_ALIGN(1) NV_RULE_GROUP_HEAD;

/* rule list storage format */
  
typedef struct {
    int numOfGroup;   /* number of groups in the list */

    NV_RULE_GROUP_HEAD head; /* rule group head */
    /* variable group name follows */
    /* rules(described by structure NV_RULE_ENTRY) follows */

    /* repeat (numOfGroup - 1) times of the above fields */
    } _WRS_PACK_ALIGN(1) NV_RULE_LIST_TBL;

/* rule storage format */

typedef struct {
    UINT16 ruleLen; /* rule length inclusive */
    UINT32 fieldBits;
    /* variable fields follows */
    
    /* repeat (ruleNum(in NV_RULE_GROUP_HEAD) - 1) times of the above fields */
    } _WRS_PACK_ALIGN(1) NV_RULE_ENTRY;



/* Locals */

/* identifications of the Firewall NV parameter blocks */

LOCAL char nvPreInputIdStr[]  = "prein";
LOCAL char nvInputIdStr[]     = "input";
LOCAL char nvForwardIdStr[]   = "forwd";
LOCAL char nvOutputIdStr[]    = "output";
LOCAL char nvPreInput6IdStr[]  = "prein6";
LOCAL char nvInput6IdStr[]     = "input6";
LOCAL char nvForward6IdStr[]   = "forwd6";
LOCAL char nvOutput6IdStr[]    = "output6";

LOCAL char * nvFileNames[] = {nvPreInputIdStr,nvInputIdStr,nvForwardIdStr,
                              nvOutputIdStr,nvPreInput6IdStr,nvInput6IdStr,
			      nvForward6IdStr,nvOutput6IdStr};
LOCAL int nvRuleIfMode = 0;

/* Local functions */

LOCAL int nvRuleDataSet (FW_RULE_ENTRY *, char *, int);
LOCAL int nvRuleDataGet (FW_RULE_ENTRY *, char *,int);
LOCAL int nvDataToListRestore (void);
LOCAL int ruleGrpNvFmtCvt (char *, FW_GROUP_HEAD_ENTRY *);
LOCAL int nvRuleGroupGet (FW_LOC_TYPE, int, NV_RULE_GROUP_HEAD *, int);

/******************************************************************************
*
* fwNvRuleLibInit - initialize the rule library NV storage interface
*
* This routine first restores the IP Firewall rule lists from the NV storage.
* If successful, it then enables the rule NV storage interface. The API
* fwNvRuleListSave() should not be called before this function is successfully
* completed.
*
* RETURNS: OK or ERROR if fails
*/

int fwNvRuleLibInit (void)
    {
    if (nvRuleIfMode)
        return OK;   /* only allow initialize once */

    if (fwNvInstalled() == FALSE)
        return ERROR;

    if (nvDataToListRestore() == OK)
        {
        nvRuleIfMode = NV_RULE_IF_ENABLE;
        return OK;
        }
    else
        {
	nvRuleIfMode = NV_RULE_IF_DISABLE;
        return ERROR;
        }
    } 

/******************************************************************************
*
* nvDataToListRestore - restore the IP Firewall rule lists from NV storage
*
*/

LOCAL int nvDataToListRestore (void)
    {
    int groupCnt;
    LIST * pList;
    char * fileName;
    int loc;
    int j,k;
    int grpLen;
    int ruleLen;
    void * groupId;
    NV_RULE_GROUP_HEAD * pGrpHead;
    char * pNvRule;
    FW_RULE_ENTRY rule;
    void * ruleId;
    int type;

    /* first restore the saved data to the rule lists */

    for (loc = 0; loc < FW_END_LOC; loc++)
        {
        pList = fwRuleListGet(loc);

#ifdef INET6
        if (loc >= FW_PREIN_LOC_V6)
            type = FW_RULE_TYPE_IPV6;
        else
#endif
            type = FW_RULE_TYPE_IPV4;

        /* get the total group number in the list */

        fileName = nvFileNames[loc];

        groupCnt = 0;
        fwNvParamGet(fileName,(char *)&groupCnt,4,0);
 
        for (j = 0; j < groupCnt; j++)
            {
            /* get the length first, pass third parameter as NULL */

            grpLen = nvRuleGroupGet (loc,j,NULL,0);   

            if (!grpLen)
                break;

            /* now malloc a buffer */
 
            if ((pGrpHead = malloc(grpLen)) == NULL)
                {
                printf("nvDataToListRestore: malloc1 fail: 0x%x\n",grpLen);
                return ERROR;
                }

            /* get the saved rule group */

            if (!nvRuleGroupGet (loc,j,pGrpHead,grpLen))
                {
                free(pGrpHead);
                continue;
                }

            /* retrieve the head rule */

            pNvRule = (char *)(pGrpHead + 1) + pGrpHead->nameLen;

            bzero((char *)&rule,sizeof(rule));

            ruleLen = nvRuleDataGet(&rule,pNvRule,type);
            if (!ruleLen)
                {
                free(pGrpHead);
                continue;
                }

            groupId = fwRuleGroupCreate(loc,
                            pGrpHead->nameLen? (char *)(pGrpHead + 1): NULL,
                            pGrpHead->logLen);
            fwRuleFieldSet(groupId,FW_FIELD_ALL,(UINT32)(&rule));

            /* now create the sub rules */

            pNvRule += ruleLen;
            for (k = 1; (k < pGrpHead->ruleNum) && groupId; k++)
                {
                bzero((char *)&rule,sizeof(rule));
                pNvRule += nvRuleDataGet(&rule,pNvRule,type);   
                ruleId = fwRuleCreate (groupId);
                fwRuleFieldSet(ruleId, FW_FIELD_ALL,(UINT32)(&rule));
                }
            free(pGrpHead);
            }
        fwNvParamClose(fileName);
        }
    return OK;
    }
                 
/*****************************************************************************
*
* fwNvRuleListSave - store the specified rule list into NV storage
*
* This routine stores the given rule list into NV storage. User must not modify
* the given rule list when this function is called.
*
* RETURN OK or ERROR if fails.
* 
*/
STATUS fwNvRuleListSave
    (
    FW_LOC_TYPE loc  /* which rule list */
    )
    {
    char * fileName;
    LIST * pGrpList;
    char * pNvTemp;
    int len = 0;
    FW_GROUP_HEAD_ENTRY * pHead;
    NODE * pRuleNode;
    int groupCnt;

    if (loc >= FW_END_LOC)
        return ERROR;
   
    if (nvRuleIfMode != NV_RULE_IF_ENABLE)
        return ERROR;

    pGrpList = fwRuleListGet(loc);

    /* calculate approximate temporary memory space needed for the operation*/

    pHead = (FW_GROUP_HEAD_ENTRY *)lstFirst(pGrpList);
    while (pHead)
	{
        /* add the length of the rule head entry */

        len += sizeof(FW_GROUP_HEAD_ENTRY);

        if (pHead->attr.pGrpName)
            len += strlen(pHead->attr.pGrpName) + 1;

        /* add the length of the rest sub rules */

        pRuleNode = lstFirst(&pHead->ruleList);  

        /*the first one is head rule, skip it */

        pRuleNode = lstNext(pRuleNode);
        while (pRuleNode)
            {
            len += sizeof(FW_RULE_ENTRY);
            pRuleNode = lstNext(pRuleNode);
            }
	pHead = (FW_GROUP_HEAD_ENTRY *)lstNext(&pHead->node);
	}

    if (!len)
        {
        /* this is the case to simply clear the existing storage for a 
         * given filtering location.
         */

        fileName = nvFileNames[loc];
        fwNvParamSet(fileName,(char *)&len,sizeof(len), 0);
        fwNvParamClose(fileName);
        
	return OK;   /* nothing to save */
        }

    /* allocate a temporary memory */

    if ((pNvTemp = (char *)malloc(len + NUMOFGROUP_FIELD_SIZE)) == NULL)
	{
	printf("fwNvRuleListSave: ERROR malloc fails\n");
	return ERROR;
	}

    pHead = (FW_GROUP_HEAD_ENTRY *)lstFirst(pGrpList);
    len = 0;
    groupCnt = 0;

    /* Convert the rule list into the NV storage format in the temp memory */
 
    while (pHead)
        {
        len += ruleGrpNvFmtCvt(pNvTemp + NUMOFGROUP_FIELD_SIZE + len,pHead);
	pHead = (FW_GROUP_HEAD_ENTRY *)lstNext(&pHead->node);
        groupCnt++;
        }

    /* store the group count at the beginning */

    *(int *)pNvTemp = groupCnt;

    /* Now save to NV storage */

    fileName = nvFileNames[loc];
    fwNvParamSet(fileName,pNvTemp,len + NUMOFGROUP_FIELD_SIZE, 0);
    free(pNvTemp);
    fwNvParamClose(fileName);
    return OK;
    }

/*****************************************************************************
*
* ruleGrpNvFmtCvt - Convert rule group into NV storage format image
*
* RETRUN the length of converted image.
*
*/
LOCAL int ruleGrpNvFmtCvt
    (
    char * pBuf,  /* the buffer to store the rule group's NV storage image */
    FW_GROUP_HEAD_ENTRY * pHead  /* point to the rule group to be saved */
    )
    {
    UINT32 headLen = sizeof(NV_RULE_GROUP_HEAD);
    NV_RULE_GROUP_HEAD * pNvHead;
    FW_RULE_ENTRY_NODE * pRuleEntry;
    char * pNvRule;
    int ruleCnt = 0;
    int ruleLen = 0;

    pNvHead = (NV_RULE_GROUP_HEAD *)pBuf;

    pNvHead->logLen  = pHead->attr.logLen;
    pNvHead->nameLen = pHead->attr.pGrpName ? 
                       strlen(pHead->attr.pGrpName) + 1 : 0;
    if (pNvHead->nameLen != 0)
        {
        bcopy(pHead->attr.pGrpName,(char *)(&pNvHead->nameLen) + 1,
	          pNvHead->nameLen);
        headLen += pNvHead->nameLen;
        }

    pNvRule = (char *)pNvHead + headLen;
    pRuleEntry = (FW_RULE_ENTRY_NODE *)lstFirst(&pHead->ruleList);

    while (pRuleEntry)
        {
        ruleLen += nvRuleDataSet(&pRuleEntry->rule,pNvRule + ruleLen,
				  pHead->attr.type);
        pRuleEntry = (FW_RULE_ENTRY_NODE *)lstNext(&pRuleEntry->node);
        ruleCnt++;
        }

    pNvHead->ruleNum = ruleCnt;
    pNvHead->grpLen = headLen + ruleLen;

    return pNvHead->grpLen;
    }
 
/******************************************************************************
*
* nvRuleDataSet - Set rule data in NV storage format
*
*/


LOCAL int nvRuleDataSet
    (
    FW_RULE_ENTRY * pRule,  
    char * pNvRule,  /* rule start point in NV storage format image buffer */
    int type
    )
    { 
    char * pAddrStart;
    char * pAddrEnd;
    int addrSize;
    int proto;
    UINT32 fieldBits = 0;
    UINT16 ruleLen = 0;
    
    ruleLen = sizeof(NV_RULE_ENTRY); /*skip the NV format rule header for now*/

    if (pRule->srcIf.name[0] != 0)
        {
        fieldBits |= NV_RULE_SRCIF_BIT;
        bcopy(pRule->srcIf.name,pNvRule+ruleLen,END_NAME_MAX);
        ruleLen += END_NAME_MAX;
        pNvRule[ruleLen++] = pRule->srcIf.unit;
        }

    if (pRule->dstIf.name[0] != 0)
        {
        fieldBits |= NV_RULE_DSTIF_BIT;
        bcopy(pRule->dstIf.name,pNvRule+ruleLen,END_NAME_MAX);
        ruleLen += END_NAME_MAX;
        pNvRule[ruleLen++] = pRule->dstIf.unit;
        }

    pAddrStart = NULL;
    pAddrEnd   = NULL;

#ifdef INET6
    if (type & FW_RULE_TYPE_IPV6)
        {
        if (V6ADDR32_IS_ASSIGNED(pRule->srcStartV6Addr32))        
            pAddrStart = (char *)pRule->srcStartV6Addr32;

        if (V6ADDR32_IS_ASSIGNED(pRule->srcEndV6Addr32))
            pAddrEnd = (char *)pRule->srcEndV6Addr32;

        addrSize = sizeof(struct in6_addr);
        }
    else
#endif
        {
        if (pRule->srcStartV4Addr)
            pAddrStart = (char *)&pRule->srcStartV4Addr;

        if (pRule->srcEndV4Addr)
            pAddrEnd = (char *)&pRule->srcEndV4Addr;

        addrSize = sizeof(struct in_addr);
        }

    if ((pAddrStart != 0) && (pAddrEnd != 0))
        {
        fieldBits |= NV_RULE_SRCADR_BIT;
        bcopy(pAddrStart,pNvRule+ruleLen, addrSize);
        ruleLen += addrSize;
        bcopy(pAddrEnd,pNvRule+ruleLen, addrSize);
        ruleLen += addrSize;
        pAddrStart = NULL;  /* reinit 'em */
        pAddrEnd   = NULL;  /* reinit 'em */
        }


#ifdef INET6
    if (type & FW_RULE_TYPE_IPV6)
        {
        if (V6ADDR32_IS_ASSIGNED(pRule->dstStartV6Addr32))
            pAddrStart = (char *)pRule->dstStartV6Addr32;

        if (V6ADDR32_IS_ASSIGNED(pRule->dstEndV6Addr32))
            pAddrEnd = (char *)pRule->dstEndV6Addr32;

        addrSize = sizeof(struct in6_addr);
        }
    else
#endif
        {
        if (pRule->dstStartV4Addr)
            pAddrStart = (char *)&pRule->dstStartV4Addr;

        if (pRule->dstEndV4Addr)
            pAddrEnd = (char *)&pRule->dstEndV4Addr;

        addrSize = sizeof(struct in_addr);
        }

    if ((pAddrStart != 0) && (pAddrEnd != 0))
        {
        fieldBits |= NV_RULE_DSTADR_BIT;
        bcopy(pAddrStart,pNvRule+ruleLen, addrSize);
        ruleLen += addrSize;
        bcopy(pAddrEnd,pNvRule+ruleLen, addrSize);
        ruleLen += addrSize;
        }

#ifdef INET6
    if (type & FW_RULE_TYPE_IPV6)
        {
        proto = pRule->protoV6;

        if (pRule->protoV6 != 0)
	    {
	    fieldBits |= NV_RULE_PROTO_BIT;
	    pNvRule[ruleLen++] = pRule->protoV6;
	    }

        if (pRule->extListV6.opType != 0)
            {
            fieldBits |= NV_RULE_EXTHDRS_BIT;
            bcopy((char *)&pRule->extListV6.opType,pNvRule+ruleLen, 
                  sizeof(FW_RULE_V6EXT_HDRS) - 1);
            ruleLen += (sizeof(FW_RULE_V6EXT_HDRS) - 1);
            }
        
        if (pRule->pktSizeV6.start != 0 || pRule->pktSizeV6.end != 0)
            {
            fieldBits |= NV_RULE_PKTSIZE_BIT;
            bcopy((char *)&pRule->pktSizeV6.start,pNvRule+ruleLen,
                                                  PKTSIZE_FIELD_SIZE);
            ruleLen += PKTSIZE_FIELD_SIZE;
            }

        if (pRule->fLabelV6.start != 0 || pRule->fLabelV6.end != 0)
            {
            fieldBits |= NV_RULE_FLOWLABEL_BIT;
            bcopy((char *)&pRule->fLabelV6.start,pNvRule+ruleLen,
                                                  FLOWLABEL_FIELD_SIZE);
            ruleLen += FLOWLABEL_FIELD_SIZE;
            }
        }
    else   /* V4 */   
#endif  
        {
        if (pRule->hdrLenV4 != 0)
            {
	    fieldBits |= NV_RULE_HDRLEN_BIT;
	    pNvRule[ruleLen++] = pRule->hdrLenV4;
	    }

        proto = pRule->protoV4;
        if (pRule->protoV4 != 0)
	    {
	    fieldBits |= NV_RULE_PROTO_BIT;
	    pNvRule[ruleLen++] = pRule->protoV4;
	    }

        if (pRule->fragV4 != 0)
            {
	    fieldBits |= NV_RULE_FRAG_BIT;
	    pNvRule[ruleLen++] = pRule->fragV4;
	    }

        if (pRule->pktSizeV4.start != 0 || pRule->pktSizeV4.end != 0)
            {
            fieldBits |= NV_RULE_PKTSIZE_BIT;
            bcopy((char *)&pRule->pktSizeV4.start,pNvRule+ruleLen,
                                                  PKTSIZE_FIELD_SIZE);
            ruleLen += PKTSIZE_FIELD_SIZE;
            }
        }      

    if (proto == IPPROTO_TCP)
        {
        if (pRule->tcpSrcPortStart != 0 || pRule->tcpSrcPortEnd != 0)
            {
            fieldBits |= NV_RULE_TCPSPORT_BIT;
            bcopy((char *)&pRule->tcpSrcPortStart,pNvRule+ruleLen, 
                  PKTPORTS_FIELD_SIZE);
            ruleLen += PKTPORTS_FIELD_SIZE;
            }

        if (pRule->tcpDstPortStart != 0 || pRule->tcpDstPortEnd != 0)
            {
            fieldBits |= NV_RULE_TCPDPORT_BIT;
            bcopy((char *)&pRule->tcpDstPortStart,pNvRule+ruleLen, 
                  PKTPORTS_FIELD_SIZE);
            ruleLen += PKTPORTS_FIELD_SIZE;
            }

        if (pRule->tport.tcp.tcpFlag.mask != 0)
            {
            fieldBits |= NV_RULE_TCPFLAG_BIT;
            bcopy((char *)&pRule->tport.tcp.tcpFlag,pNvRule+ruleLen, 4);
            ruleLen += 4;
            }
        }
    else if (proto == IPPROTO_UDP)
        {
        if (pRule->udpSrcPortStart != 0 || pRule->udpSrcPortEnd != 0)
            {
            fieldBits |= NV_RULE_UDPSPORT_BIT;
            bcopy((char *)&pRule->udpSrcPortStart,pNvRule+ruleLen, 
                  PKTPORTS_FIELD_SIZE);
            ruleLen += PKTPORTS_FIELD_SIZE;
            }

        if (pRule->udpDstPortStart != 0 || pRule->udpDstPortEnd != 0)
            {
            fieldBits |= NV_RULE_UDPDPORT_BIT;
            bcopy((char *)&pRule->udpDstPortStart,pNvRule+ruleLen, 
                  PKTPORTS_FIELD_SIZE);
            ruleLen += PKTPORTS_FIELD_SIZE;
            }
        }
    else if (proto == IPPROTO_ICMP || proto == IPPROTO_ICMPV6)
        {
        if (pRule->tport.icmp.type != FW_INVALID_ICMP_TYPE)
            {
            fieldBits |= NV_RULE_ICMPTYPE_BIT;
            bcopy((char *)&pRule->tport.icmp.type,pNvRule+ruleLen, 4);
            ruleLen += 4;
            }
        }

    if (pRule->timeOfDay.days != 0)
        {
        fieldBits |= NV_RULE_TIMEDAY_BIT;
        bcopy((char *)&pRule->timeOfDay,pNvRule+ruleLen,
               sizeof(FW_RULE_TIMEOFDAY));
        ruleLen += sizeof(FW_RULE_TIMEOFDAY);
        }
        
    if (pRule->connTrack.entity != 0)
        {
        fieldBits |= NV_RULE_STATE_BIT;
        bcopy((char *)&pRule->connTrack.entity,pNvRule+ruleLen, sizeof(UINT16));
        ruleLen += sizeof(UINT16);
        bcopy((char *)&pRule->connTrack.state, pNvRule+ruleLen, sizeof(UINT16));
        ruleLen += sizeof(UINT16);
        }

    /* the last one action code is always there */

    bcopy((char *)&pRule->actions,pNvRule+ruleLen, sizeof(UINT32));
    ruleLen += sizeof(UINT32);
             
    /* write to the rule length and fieldbits  */

    pNvRule[OFFSET(NV_RULE_ENTRY,ruleLen)]     = *(char *)(&ruleLen);
    pNvRule[OFFSET(NV_RULE_ENTRY,ruleLen) + 1] = *((char *)(&ruleLen) + 1);
    pNvRule[OFFSET(NV_RULE_ENTRY,fieldBits)]     = *(char *)(&fieldBits);
    pNvRule[OFFSET(NV_RULE_ENTRY,fieldBits) + 1] = *((char *)(&fieldBits) + 1);
    pNvRule[OFFSET(NV_RULE_ENTRY,fieldBits) + 2] = *((char *)(&fieldBits) + 2);
    pNvRule[OFFSET(NV_RULE_ENTRY,fieldBits) + 3] = *((char *)(&fieldBits) + 3);

    return ruleLen;
    }
 
/******************************************************************************
*
* nvRuleDataGet - Get rule data from NV storage format
*
*/


LOCAL int nvRuleDataGet
    (
    FW_RULE_ENTRY * pRule,  /* buffer to hold the rule */
    char * pNvRule,  /* point to NV format rule */
    int type
    )
    { 
    UINT32 fieldBits = 0;
    UINT16 ruleLen = 0;
    int proto;

    ruleLen = sizeof(NV_RULE_ENTRY);

    /* get the fieldbits  */

    bcopy(pNvRule + OFFSET(NV_RULE_ENTRY,fieldBits),(char *)&fieldBits,
          sizeof(UINT32));

    if (fieldBits & NV_RULE_SRCIF_BIT)
        {
        bcopy(pNvRule+ruleLen,pRule->srcIf.name,END_NAME_MAX);
        ruleLen += END_NAME_MAX;
        pRule->srcIf.unit = pNvRule[ruleLen++];
        }

    if (fieldBits & NV_RULE_DSTIF_BIT)
        {
        bcopy(pNvRule+ruleLen,pRule->dstIf.name,END_NAME_MAX);
        ruleLen += END_NAME_MAX;
        pRule->dstIf.unit = pNvRule[ruleLen++];
        }

    if (fieldBits & NV_RULE_SRCADR_BIT)
        {
#ifdef INET6
        if (type & FW_RULE_TYPE_IPV6)
            {
            bcopy(pNvRule+ruleLen,(char *)pRule->srcStartV6Addr8, 
                   sizeof(struct in6_addr));
            ruleLen += sizeof(struct in6_addr);
            bcopy(pNvRule+ruleLen,(char *)pRule->srcEndV6Addr8, 
                  sizeof(struct in6_addr));
            ruleLen += sizeof(struct in6_addr);
            }
        else  /* V4 */
#endif
            {
            bcopy(pNvRule+ruleLen,(char *)&pRule->srcStartV4Addr, 
                   sizeof(struct in_addr));
            ruleLen += sizeof(struct in_addr);
            bcopy(pNvRule+ruleLen,(char *)&pRule->srcEndV4Addr, 
                  sizeof(struct in_addr));
            ruleLen += sizeof(struct in_addr);
            }
        }

    if (fieldBits & NV_RULE_DSTADR_BIT)
        {
#ifdef INET6
        if (type & FW_RULE_TYPE_IPV6)
            {
            bcopy(pNvRule+ruleLen,(char *)pRule->dstStartV6Addr8, 
                                   sizeof(struct in6_addr));
            ruleLen += sizeof(struct in6_addr);
            bcopy(pNvRule+ruleLen,(char *)pRule->dstEndV6Addr8, 
                  sizeof(struct in6_addr));
            ruleLen += sizeof(struct in6_addr);
            }
        else
#endif
            {
            bcopy(pNvRule+ruleLen,(char *)&pRule->dstStartV4Addr, 
                                   sizeof(struct in_addr));
            ruleLen += sizeof(struct in_addr);
            bcopy(pNvRule+ruleLen,(char *)&pRule->dstEndV4Addr, 
                  sizeof(struct in_addr));
            ruleLen += sizeof(struct in_addr);
            }
        }

#ifdef INET6
    if (type & FW_RULE_TYPE_IPV6)
        {
        if (fieldBits & NV_RULE_PROTO_BIT)
            pRule->protoV6 = pNvRule[ruleLen++];

        if (fieldBits & NV_RULE_EXTHDRS_BIT)
            {
            bcopy(pNvRule+ruleLen,(char *)&pRule->extListV6.opType,
                 sizeof(FW_RULE_V6EXT_HDRS) - 1);
            ruleLen += (sizeof(FW_RULE_V6EXT_HDRS) - 1);
            }  
      
        if (fieldBits & NV_RULE_PKTSIZE_BIT)
            {
            bcopy(pNvRule+ruleLen,(char *)&pRule->pktSizeV6.start,
                 sizeof(PKTSIZE_FIELD_SIZE));
            ruleLen += sizeof(PKTSIZE_FIELD_SIZE);
            }  

        if (fieldBits & NV_RULE_FLOWLABEL_BIT)
            {
            bcopy(pNvRule+ruleLen,(char *)&pRule->fLabelV6.start,
                 FLOWLABEL_FIELD_SIZE);
            ruleLen += FLOWLABEL_FIELD_SIZE;
            }  
        proto = pRule->protoV6;
        }
    else   /* V4 */
#endif
        { 
        if (fieldBits & NV_RULE_HDRLEN_BIT)
            pRule->hdrLenV4 = pNvRule[ruleLen++]; 

        if (fieldBits & NV_RULE_PROTO_BIT)
            pRule->protoV4 = pNvRule[ruleLen++]; 

        if (fieldBits & NV_RULE_FRAG_BIT)
            pRule->fragV4 = pNvRule[ruleLen++];

        if (fieldBits & NV_RULE_PKTSIZE_BIT)
            {
            bcopy(pNvRule+ruleLen,(char *)&pRule->pktSizeV4.start,
                  PKTSIZE_FIELD_SIZE);
            ruleLen += PKTSIZE_FIELD_SIZE;
            }
        proto = pRule->protoV4;
        }

    if (proto == IPPROTO_TCP)
        {
        if (fieldBits & NV_RULE_TCPSPORT_BIT)
            {
            bcopy(pNvRule+ruleLen,(char *)&pRule->tcpSrcPortStart, 
                  PKTPORTS_FIELD_SIZE);
            ruleLen += PKTPORTS_FIELD_SIZE;
            }

        if (fieldBits & NV_RULE_TCPDPORT_BIT)
            {
            bcopy(pNvRule+ruleLen,(char *)&pRule->tcpDstPortStart, 
                  PKTPORTS_FIELD_SIZE);
            ruleLen += PKTPORTS_FIELD_SIZE;
            }

        if (fieldBits & NV_RULE_TCPFLAG_BIT)
            {
            bcopy(pNvRule+ruleLen,(char *)&pRule->tport.tcp.tcpFlag, 4);
            ruleLen += 4;
            }
        }
    else if (proto == IPPROTO_UDP)
        {
        if (fieldBits & NV_RULE_UDPSPORT_BIT)
            {
            bcopy(pNvRule+ruleLen,(char *)&pRule->udpSrcPortStart, 
                  PKTPORTS_FIELD_SIZE);
            ruleLen += PKTPORTS_FIELD_SIZE;
            }

        if (fieldBits & NV_RULE_UDPDPORT_BIT)
            {
            bcopy(pNvRule+ruleLen,(char *)&pRule->udpDstPortStart, 
                  PKTPORTS_FIELD_SIZE);
            ruleLen += PKTPORTS_FIELD_SIZE;
            }
        }
    else if (proto == IPPROTO_ICMP || proto == IPPROTO_ICMPV6)
        {
        if (fieldBits & NV_RULE_ICMPTYPE_BIT)
            {
            bcopy(pNvRule+ruleLen,(char *)&pRule->tport.icmp.type, 4);
            ruleLen += 4;
            }
        else
            pRule->tport.icmp.type = FW_INVALID_ICMP_TYPE;
        }

    if (fieldBits & NV_RULE_TIMEDAY_BIT)
        {
        bcopy(pNvRule+ruleLen,(char *)&pRule->timeOfDay,
               sizeof(FW_RULE_TIMEOFDAY));
        ruleLen += sizeof(FW_RULE_TIMEOFDAY);
        }
        
    if (fieldBits & NV_RULE_STATE_BIT)
        {
        bcopy(pNvRule+ruleLen,(char *)&pRule->connTrack.entity, sizeof(UINT16));
        ruleLen += sizeof(UINT16);
        bcopy(pNvRule+ruleLen,(char *)&pRule->connTrack.state, sizeof(UINT16));
        ruleLen += sizeof(UINT16);
        }

    /* the action code is always there */

    bcopy(pNvRule+ruleLen,(char *)&pRule->actions, sizeof(UINT32));
    ruleLen += sizeof(UINT32);

    return ruleLen;
    }

/*****************************************************************************
*
* nvRuleGroupGet - Get the specified rule group from NV storage
*
* This routine retrieves the specified rule group from NV storage. However if
* the parameter pNvHead is NULL, this routine simply returns the total length
* of the rule group.
*
* RETRUN the length of read data or the group length.
*
*/
LOCAL int nvRuleGroupGet
    (
    FW_LOC_TYPE loc,
    int grpNum,     /* the group number in the order stored in the NV storage*/
    NV_RULE_GROUP_HEAD * pNvHead,  /* buffer to hold the retrieved data */
    int bufLen                     /* the length of the above buffer */
    )
    {
    char * fileName;
    UINT32 groupCnt;
    UINT32 cumGrpLen;
    UINT32 grpLen = 0;
    int i;

    if (loc >= FW_END_LOC)
        return 0;

    fileName = nvFileNames[loc];

    /* get the total group count */

    fwNvParamGet(fileName,(char *)&groupCnt,4,0);

    if (groupCnt < grpNum)
        return 0;

    cumGrpLen = 4;

    /* advance to the location of the group Head */

    for (i = 0; i < grpNum; i++)
        {
        fwNvParamGet(fileName,(char *)&grpLen,4,cumGrpLen);
        cumGrpLen += grpLen;
        }

    if (pNvHead == NULL)
        {
        /* only ask for the group length */

        if (fwNvParamGet(fileName,(char *)&grpLen,4,cumGrpLen) == 4)
	    return grpLen;
        else
            return 0;
        }

    /* retrieve the head */

    return fwNvParamGet(fileName,(char *)pNvHead,bufLen,cumGrpLen);
    }

/*******************************************************************************
*
* fwNvRuleLibReset - Reset this library initial state to un-initialized
*
* This routine resets the library initial state to un-initialized. 
* Saved rule lists will not restored if the Non-Volatile storage is not 
* initialized before fwNvRuleLibInit() is automatically invoked in the 
* firewall initialization routine. In this case, call this function and 
* then call fwNvRuleLibInit() again. 
*
* For example, if you use the target server file system as your NV storage,
* the target server will most likely be initialized after the firewall. 
* That is, fwNvRuleLibInit() may be called before the target server file
* system is initialized, and will fail. To fix this, call this function
* and then call fwNvRuleLibInit() again.
*
* RETURNS: N/A
*
* NOMANUAL
*/

void fwNvRuleLibReset ()
    {
    nvRuleIfMode = 0;
    }