⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nat_fragment.c

📁 VXWORKS NAT 部分源代码2 有兴趣朋友可以参考下
💻 C
📖 第 1 页 / 共 2 页
字号:
        {
        if (pEntry->flag & ENTRY_IN_USE)
            {
            if (pEntry->orgSrcAddr == pIpPacket->header.source_address &&
                pEntry->orgDstAddr == pIpPacket->header.destination_address &&
                pEntry->fragId     == pIpPacket->header.identifier &&
                pEntry->proto      == pIpPacket->header.protocol)
                break;   /* found one */

            }
        pEntry = (NAT_FRAGMENT_ENTRY *)DLL_NEXT(&pEntry->u.node);
        }
    return pEntry;
    }

/*****************************************************************************
*
* natFragAddrTranslate - Perform the fragment address translation
*
* This routine first finds the translated address from the translation entry,
* and then applies this new address to either the fragment's source address or
* destination address depending on which port the fragment comes in. This 
* routine also takes consideration of the scenario described in RFC3022, 
* section 6.3. If that scenario occurs, the fragments other than for the first
* connection will be dropped. This routine finally checks whether this 
* fragment is last one. If so, the translation entry allocated for this
* fragmented datagram is freed.
*
* RETURNS: PASS or FAIL 
*
*/
enum TEST natFragAddrTranslate
    (
    int    portType,      /* Global or local port type */
    IP_PACKET * pIpPacket /* the fragment packet */
    )
    {
    int inx;
    NAT_FRAGMENT_ENTRY * pCacheEntry;
    NAT_FRAGMENT_ENTRY * pSearchEntry;
    IP_ADDRESS orgAddress;
    IP_ADDRESS *pAddrToChange = NULL;
    int portInx;

    portInx = portType == NAT_GLOBAL_PORT?
                  GLOBAL_PORT_INX:
                  LOCAL_PORTS_INX;

    inx = pIpPacket->header.identifier & FRAG_ID_HASH_MASK;
    pCacheEntry = &pFragResrcDesc[portInx]->pArray[inx];
    pSearchEntry = pCacheEntry;

    if ((pSearchEntry = fragTranIdMatch(pCacheEntry, pIpPacket)) == NULL)
        {
        /* if coming from local ports, possibly the collision packets */

        DBG_PRINT(("No translation, Packets from port %d dropped\n",portInx));
        return FAIL;
        }

    if (portType == NAT_GLOBAL_PORT)
        {

        pAddrToChange = &pIpPacket->header.destination_address;

        DBG_PRINT(("Global Tran: inx=0x%x, srcAdr=0x%x, dstAdr=0x%x, id=0x%x\n",
                  inx,(int)pSearchEntry->orgSrcAddr,
		  (int)pSearchEntry->orgDstAddr,
                  (int)pSearchEntry->fragId));
        }
    else   /* local ports */
        {
        pAddrToChange = &pIpPacket->header.source_address;

        DBG_PRINT(("Local Tran: inx=0x%x,srcAdr=0x%x,dstAdr=0x%x,id=0x%x\n",
              inx,(int)pSearchEntry->orgSrcAddr,(int)pSearchEntry->orgDstAddr,
                  pSearchEntry->fragId));
        }
  
    /* This flag is set by default. The IP header checksum will be calculated
     * by the ip_output routine if this flag is set. Therefore no need to do
     * the IP header checksum fixup here if the condition is true.
     */

    if (_ipCfgFlags & IP_DO_CHECKSUM_SND)

        *pAddrToChange = pSearchEntry->newAddr;

    else
        {
        orgAddress = *pAddrToChange;

        *pAddrToChange = pSearchEntry->newAddr;

        checksum_fixup ((BYTE *) &pIpPacket->header.header_checksum,
                    (BYTE *) &orgAddress, sizeof (IP_ADDRESS),
                    (BYTE *) pAddrToChange,
                    sizeof (IP_ADDRESS));
        }

    /* now check whether it is the last fragment */

    if (!(pIpPacket->header.fragment & IP_FRAGMENT_FLAG_MORE_FRAGMENTS)) 
        {
        /* last fragment, free the entry */

        if (pSearchEntry == pCacheEntry)
            {
            DBG_PRINT(("Last fragment, cache entry freed\n"));

            pSearchEntry->flag = ENTRY_FREE;
            }
        else
            {
            DBG_PRINT(("Last fragment, list entry removed\n"));

            /* Not the cache entry, simply remove it from the list */

            dllRemove(&pCacheEntry->u.list, &pSearchEntry->u.node);

            /* put back the freed entry to the free list */
 
            dllAdd(&pFragResrcDesc[portInx]->fragFreeList,
                             &pSearchEntry->u.node);
            }

        if (pFragResrcDesc[portInx]->outstandingEntries)
	    pFragResrcDesc[portInx]->outstandingEntries--;
        }
    return PASS;
    } 

/******************************************************************************
*
* natFragTranAddrSave - Save the translated address
*
* This routine is called to save the result of the translated address derived
* by the NAT address translation engine on the first fragment of the datagram.
* The result is saved to the corresponding fragment translation entry. 
* This routine also check whether the collision problem described by RFC3022, 
* section 6.3 exist. If so this fragment will be dropped.
*
* RETURNS: PASS or FAIL
*
*/

enum TEST natFragTranAddrSave
    (
    int    portType,      /* global port or local ports */ 
    void * pEntry,        /* this fragment's translation entry */
    IP_ADDRESS newAddr    /* The translated address */
    )
    {
    NAT_FRAGMENT_ENTRY * pCacheEntry = NULL;
    NAT_FRAGMENT_ENTRY * pSearchEntry = NULL;
    NAT_FRAGMENT_ENTRY * pCurEntry;  /* this fragment's translation entry */
    int inx;

    pCurEntry = (NAT_FRAGMENT_ENTRY *)pEntry;

    /* save the translated address */

    pCurEntry->newAddr = newAddr;

    DBG_PRINT(("portType: %s, translated address: 0x%x\n",
               portType == NAT_GLOBAL_PORT? "GLOBAL_PORT": "LOCAL_PORT",
               (int)newAddr));

    if (portType == NAT_GLOBAL_PORT)
	return PASS;  /* done */

    else  /* local ports */
	{
        inx = pCurEntry->fragId & FRAG_ID_HASH_MASK;
        pCacheEntry = &pFragResrcDesc[LOCAL_PORTS_INX]->pArray[inx];
        pSearchEntry = pCacheEntry;

        /* if the packet coming from the local port, there exists a collision
         * problem described by RFC3022, section 6.3.
         * We'll keep the first session alive and drop the second one. 
	 * A further step may be to defer sending the second datagram after 
	 * the first one is done. This requires to queue up all the fragments
	 * related to this datagram and add to the netTask after the first one
	 * is done. Don't know if worth the effort 
         */

	/* check if a collision entry exists */

        while (pSearchEntry)
            {
            if (pSearchEntry != pCurEntry)
                {
                if (pSearchEntry->orgDstAddr == pCurEntry->orgDstAddr &&
                    pSearchEntry->fragId     == pCurEntry->fragId &&
                    pSearchEntry->proto      == pCurEntry->proto &&
                    pSearchEntry->newAddr    == newAddr)
                    break;   /* found one */

                }
            pSearchEntry =(NAT_FRAGMENT_ENTRY *)DLL_NEXT(&pSearchEntry->u.node);
            }
     
        if (pSearchEntry != NULL) 
            {
            /*  Fragments translated by this entry is in collistion*/

            DBG_PRINT(("collision entry\n"));

	    /* remove the translation entry */

            if (pCurEntry == pCacheEntry)
		pCurEntry->flag = ENTRY_FREE;
            else
	        {
                /* remove from the list and add it back to free list */

		dllRemove(&pCacheEntry->u.list, &pCurEntry->u.node);
		dllAdd(&pFragResrcDesc[LOCAL_PORTS_INX]->fragFreeList,
                       &pCurEntry->u.node);
                }

            if (pFragResrcDesc[LOCAL_PORTS_INX]->outstandingEntries)           
                pFragResrcDesc[LOCAL_PORTS_INX]->outstandingEntries--;

            return FAIL;   /* drop the current fragment  */
            }

        return PASS;
        }
    }

/******************************************************************************
*
* natFragTranTimerProcess - Process the fragment translation timer events.
*
* This routine checks if the translation entry has timed out at the 1 second
* (default) interval. The timeout value is set same as the TTL value in the IP
* header. Normally the translation entry is deleted when the last fragment is
* processed. In the case the last fragment never comes, this routine will do
* the job.
*
* The actual work is done in the netTask context just as the main NAT 
* translation engine does to prevent the race condition.
*
* RETURNS: NONE
*/

void natFragTranTimerProcess (void)
    {
    int portInx;

    /* check if there is outstanding translation entries, if so, fire the
     * timer event function to start countdown
     */

    for (portInx = 0; portInx < 2; portInx++)
        {
	if (pFragResrcDesc[portInx]->outstandingEntries)
            netJobAdd((FUNCPTR)fragTranTimerNetJob,portInx,0,0,0,0); 
        }
    }

/****************************************************************************
*
* fragTranTimerNetJob - Fragment translation timer net job.
*
* This function performs the actual work of processing the fragment 
* translation timer events in the netTask context.
* 
*/

LOCAL void fragTranTimerNetJob 
    (
    int portInx
    )
    {
    int inx;
    int count;

    for (inx = 0; inx < FRAG_CACHE_ARRAY_LEN; inx++)
        {
        count = entryTimerEventProcess(&pFragResrcDesc[portInx]->pArray[inx],
                              &pFragResrcDesc[portInx]->fragFreeList);
        if (count)
            {
            if (pFragResrcDesc[portInx]->outstandingEntries >= count)
		pFragResrcDesc[portInx]->outstandingEntries -= count;
            else
		pFragResrcDesc[portInx]->outstandingEntries = 0;
            }
        }
    }

/*****************************************************************************
*
* entryTimerEventProcess - Process the fragment translation entry's timeout.
*
* RETURNS: number of the translation entries removed
*/

LOCAL int entryTimerEventProcess
    (
    NAT_FRAGMENT_ENTRY * pCacheEntry,  /* the cache entry */
    DL_LIST * pFreeList       /* the list to put back the free entries */
    )
    {
    NAT_FRAGMENT_ENTRY * pEntry;
    NAT_FRAGMENT_ENTRY * pNextEntry;
    int retCount = 0;

    pEntry = pCacheEntry;

    while (pEntry)
        {
        pNextEntry = (NAT_FRAGMENT_ENTRY *)DLL_NEXT(&pEntry->u.node);

        /* decrement the 1 second timer counter */

        if (pEntry->flag & ENTRY_IN_USE)
            { 
            if (pEntry->ttl)
                pEntry->ttl--;

            if (pEntry->ttl == 0)
                {
                /* this entry timed out */
      
                if (pCacheEntry == pEntry)
                    {
                    /* this is the cache entry, mark it unused */

                    pEntry->flag = ENTRY_FREE;
                    }
                else 
                    {
                    /* list entry, remove it */

                    dllRemove(&pCacheEntry->u.list, &pEntry->u.node);

                    /* put back the freed entry to the free list */
 
                    dllAdd(pFreeList, &pEntry->u.node);
                    }
                retCount++;
                }
            }
        pEntry =pNextEntry;
        }
    return retCount;
    }

#ifdef FRAGMENT_DEBUG

/*****************************************************************************
*
* natFragShow - Display the usage of the translation entries 
*
* This routine is for debug purpose
*
*/

void natFragShow (void)
    {
    NAT_FRAGMENT_ENTRY * pEntry;
    NAT_FRAGMENT_ENTRY * pCacheEntry;
    int portNum;
    int inx;
    int cacheEntryCnt;
    int listEntryCnt;
    int listFreeCnt;
    DL_NODE * pNode;

    listFreeCnt = 0;
    listEntryCnt  = 0;
    cacheEntryCnt = 0;
    for (portNum = 0; portNum < 2; portNum++)
        {

        for (inx = 0; inx < FRAG_CACHE_ARRAY_LEN; inx++)
            {
            pCacheEntry = &pFragResrcDesc[portNum]->pArray[inx];
            pEntry = pCacheEntry;
            if (pEntry->flag & ENTRY_IN_USE)
                cacheEntryCnt++;

            pEntry = (NAT_FRAGMENT_ENTRY *)DLL_NEXT(&pEntry->u.node);

            while (pEntry)
                {
                listEntryCnt++;

                pEntry = (NAT_FRAGMENT_ENTRY *)DLL_NEXT(&pEntry->u.node);
                }
            }
        }
    for (portNum = 0; portNum < 2; portNum++)
        {
        pNode = DLL_FIRST(&pFragResrcDesc[portNum]->fragFreeList);

        while (pNode)
            {
            listFreeCnt++;
            pNode = DLL_NEXT(pNode);
            }
        }
    printf("Use Cache Entries: 0x%x,Use list Entries: 0x%x,Free Entry: 0x%x\n",
            cacheEntryCnt,listEntryCnt,listFreeCnt);
    }
#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -