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

📄 nat_fragment.c

📁 vxworks下ppp的实现源码
💻 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 + -