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


/* fwExtSvcLib.c - Firewall extension handler service registration module */

/* Copyright 2005 Wind River Systems, Inc. */
#include "copyright_wrs.h"

/*
modification history
--------------------
01a,21aug05,myz  written
*/

/*
DESCRIPTION

This library provides a filtering service registration mechanism for 
the firewall extension handler. This mechanism allows user to activate and
de-activate a list of filtering services dynamically. Currently this is used 
by the HTTP content filter.
You should first create the service container, register or unregister desired 
filtering services next, and then install the service process function
fwExtSvcProcess() as the extension handler to a firewall rule.

*/

#include "fw.h"

/* filter service descriptor */
                                                                                
typedef struct {
    SEM_ID semId; /* semaphore to protect the service entry operation */
    DL_LIST list; /* service container */
    } EXT_SVC_DESC;

typedef struct {
    DL_NODE node;    
    char * pName;            /* service name */
    FW_EXTSVC_FUNCPTR pFunc; /* service function */
    void * pCtxt;            /* user supplied service specific parameter */
    UINT32 matchAction;      /* firewall match action code */
    } EXT_SVC_ENTRY;

LOCAL UINT32 dftActions = FW_ACCEPT;

/********************************************************************************
*
* fwExtSvcCreate - Create a service container 
*
* This routine creates a service container. A link list in the descriptor
* will contain all the registered services.
*
* RETURNS: the service container or NULL if fail
*/
void * fwExtSvcCreate (void)
    {
    EXT_SVC_DESC * pDesc;
                                                                                
    if ((pDesc = (EXT_SVC_DESC *)malloc(sizeof(EXT_SVC_DESC))) == NULL)
        return NULL;
                                                                                
    if ((pDesc->semId = semBCreate(SEM_Q_PRIORITY,SEM_FULL)) == NULL)
        {
        free(pDesc);
        return NULL;
        }
                                                                                
    dllInit(&pDesc->list);
    return (void *)pDesc;
    }

/********************************************************************************
* fwExtSvcDelete - Delete a service container
*
* This routine frees all the memory resource associated with the given
* service container.
*
* RETURNS: TRUE or FALSE if fails
*/
BOOL fwExtSvcDelete 
    (
    void * pContainer
    )
    {
    DL_LIST * pList;
    DL_NODE * pNode;

    if (pContainer == NULL)
        return FALSE;

    pList = &((EXT_SVC_DESC *)pContainer)->list;

    semTake(((EXT_SVC_DESC *)pContainer)->semId,WAIT_FOREVER);

    while ((pNode = dllGet(pList)) != NULL)
        free((void *)pNode);

    semGive(((EXT_SVC_DESC *)pContainer)->semId);
    semDelete(((EXT_SVC_DESC *)pContainer)->semId);
    free(pContainer);
    return TRUE;
    }

/*******************************************************************************
*
* fwExtSvcReg - Register a filtering service 
*
* This routine registers a filtering service to the given service container.
* 
* RETURNS: TRUE or FALSE if fails
*/
BOOL fwExtSvcReg
    (
    void * pContainer,          /* the service container */
    char * pSvcName,            /* the registered service name */
    FW_EXTSVC_FUNCPTR pSvc,     /* the registered service function */
    void *  svcCtxt,            /* the service specific context */
    UINT32 actions              /* the match action code */
    )
    {
    DL_LIST * pList;
    EXT_SVC_ENTRY * pNode;
    int len = 0;

    if (pContainer == NULL || pSvc == NULL)
        return FALSE;

    pList = &((EXT_SVC_DESC *)pContainer)->list;

    if (pList == NULL)
        return FALSE;

    if (pSvcName != NULL)
        len = strlen(pSvcName) + 1;

    len += sizeof(EXT_SVC_ENTRY);
    if ((pNode = (EXT_SVC_ENTRY *)malloc(len)) == NULL)
        return FALSE;
    
    if (pSvcName)
        {
        pNode->pName = (char *)(pNode + 1);
        strcpy(pNode->pName,pSvcName);
        }
    else
        pNode->pName = NULL;

    pNode->pFunc = pSvc;
    pNode->pCtxt  = svcCtxt;
    pNode->matchAction = actions;
    semTake(((EXT_SVC_DESC *)pContainer)->semId,WAIT_FOREVER);
    dllAdd(pList,&pNode->node);  
    semGive(((EXT_SVC_DESC *)pContainer)->semId);
    return TRUE;
    }

/*******************************************************************************
*
* fwExtSvcUnreg - Unregister a filtering service
*
* This routine unregisters a filtering service from the given service container.
* Either the pSvcName or pSvc will be used to find the service to unregister.
* The pSvcName is checked first. If it is NULL, then the pSvc will be used.
* 
* RETURNS: TRUE or FALSE if fails
*/

BOOL fwExtSvcUnreg
    (
    void * pContainer,          /* the service container */
    char * pSvcName,            /* the registered service name */
    FW_EXTSVC_FUNCPTR pSvc      /* the registered service function */
    )
    {
    DL_LIST * pList;
    EXT_SVC_ENTRY * pNode;

    pList = &((EXT_SVC_DESC *)pContainer)->list;

    if (pList == NULL)
        return ERROR;
                                                 
    semTake(((EXT_SVC_DESC *)pContainer)->semId,WAIT_FOREVER);
    pNode = (EXT_SVC_ENTRY *)DLL_FIRST(pList);
    while (pNode)
        {
        if (pNode->pName && pSvcName && strcmp(pNode->pName,pSvcName) == 0) 
            {
            dllRemove(pList,&pNode->node);
            semGive(((EXT_SVC_DESC *)pContainer)->semId);
            free((void *)&pNode->node);
            return TRUE;
            }

        if (pNode->pFunc == pSvc)
            {
            dllRemove(pList,&pNode->node);
            semGive(((EXT_SVC_DESC *)pContainer)->semId);
            free((void *)&pNode->node);
            return TRUE;
            }
        pNode = (EXT_SVC_ENTRY *)DLL_NEXT(&pNode->node);
        }
    semGive(((EXT_SVC_DESC *)pContainer)->semId);
    return FALSE;
    }

/*******************************************************************************
*
* fwExtSvcProcess - Process the registered services.
*
* This routine processes registered services in the sequential order. It will
* immediately return the registered firewall action code if the service returns 
* FW_SVC_MATCH_DONE. Otherwise it will continue to call the next registered
* service. All the registered services are stored in a link list. User should
* not register/un-register any services when this function is in action since
* the link list is not protected in this function. This is mainly to avoid the
* costly semaphore operations in the performance critical path. 
*
* This function should be only used as the firewall extension handler. 
*
* RETURNS: Firewall action code.
*/
UINT32 fwExtSvcProcess
    (
    FW_LOC_TYPE loc,     /* firewall filtering location */
    void * groupId,      /* the rule group ID */
    struct mbuf * pMblk, /* the IP packet */
    void * usrCtxt       /* the service container */
    )
    {
    EXT_SVC_ENTRY * pNode;
    DL_LIST * pList;

    pList = &((EXT_SVC_DESC *)usrCtxt)->list;
    pNode = (EXT_SVC_ENTRY *)DLL_FIRST(pList);

    while (pNode)
        {
        if ((*pNode->pFunc)(pMblk,pNode->pCtxt) == FW_SVC_MATCH_DONE)
            return pNode->matchAction; 
        pNode = (EXT_SVC_ENTRY *)DLL_NEXT(&pNode->node);
        }
    return dftActions;
    }

/*******************************************************************************
*
* svcPrint - Print each service
*/ 
LOCAL int svcPrint
    (
    DL_NODE * pNode,
    int arg
    )
    {
    EXT_SVC_ENTRY * pSvcNode = (EXT_SVC_ENTRY *)pNode;

    printf("ServiceNode: 0x%x, Name: %s\n",(int)pNode,pSvcNode->pName?
           pSvcNode->pName:"No Name");
    return TRUE;
    }

/******************************************************************************
*
* fwExtSvcShow - Display the services for each service container.
*
* NOMANUAL
*/
void fwExtSvcShow 
    (
    void * pContainer
    )
    {
    DL_LIST * pList;

    if (pContainer == NULL)
        return;

    pList = &((EXT_SVC_DESC *)pContainer)->list;
    semTake(((EXT_SVC_DESC *)pContainer)->semId,WAIT_FOREVER);
    dllEach(pList,(FUNCPTR)svcPrint,0);
    semGive(((EXT_SVC_DESC *)pContainer)->semId);
    }