📄 ipfrag.c
字号:
//--------------------------------------------------------------------------
// Ip Stack
//--------------------------------------------------------------------------
// IPFRAG.C
//
// Routines related to IP fragmentation
//
//
// Author: Michael A. Denio
// Copyright 1999 by Texas Instruments Inc.
//-------------------------------------------------------------------------
#include <stkmain.h>
#include "ip.h"
#define FRAG_LAST 0x80000000
#define FRAG_MIDDLE 0x40000000
#define FRAG_FIRST 0x20000000
#define FRAG_OFFSET 0x0000FFFF
REASM *_IPReasmPtr = 0;
//--------------------------------------------------------------------
// IPReasm() - Attempt to reassemble packet fragment
//
// Takes the supplied packet fragment, and attempts to reassable it
// into a complete packet. If the packet under reassembly is too large,
// the reassembly is aborted.
//--------------------------------------------------------------------
void IPReasm( HANDLE hPktIn, HANDLE hFrag, IPHDR *pIpHdr )
{
HANDLE hFragT,hFragB;
REASM *pr;
uint Offset,Valid,OffsetT;
UINT8 *pb,*pbT;
UINT16 Id;
uint tmp,hdrlen;
UINT32 dwAux1 = 0;
UINT32 dwAux2, dwTmp, dwOff, dwTmp2;
ips.dwFragments++;
// First, zap hPktIn - we just need the frag
PktSetFrag( hPktIn, 0 );
PktFree( hPktIn );
// First, try and find a partially assembled packet with this ID
Id = HNC16( pIpHdr->Id );
pr = _IPReasmPtr;
while( pr )
{
if( pr->Id == Id )
goto ReasmContinue;
pr = pr->pNext;
}
// We didn't find this Id in the list, so we'll create a new packet
// to hold it.
if( !(pr = mmAlloc( sizeof(REASM) )) )
{
ips.dwFragdropped++;
FragFree( hFrag );
return;
}
// Initialize new entry
mmZeroInit( pr, sizeof(REASM) );
pr->Type = HTYPE_IPFRAG;
pr->Id = Id;
pr->Timeout = llTimerGetTime(0) + IP_REASM_MAXTIME;
// Insert into our list
if( _IPReasmPtr )
{
pr->pNext = _IPReasmPtr;
_IPReasmPtr->pPrev = pr;
}
_IPReasmPtr = pr;
ReasmContinue:
// Now we have the packet under reassembly in "pr", and our
// particular fragment in hFrag.
// Now prepare the frag for insertion into the packet
hdrlen = (uint)(pIpHdr->VerLen & 0xF) * 4;
tmp = (uint)(HNC16( pIpHdr->TotalLen ));
dwAux2 = (UINT32)(tmp - hdrlen); // Data length of frag
FragSetAux2( hFrag, dwAux2 ); // Aux2 = Length
tmp = HNC16( pIpHdr->FlagOff );
// If DONT_FRAG is set, we should never have got here!
if( tmp & IP_DF )
{
FragFree( hFrag );
IPReasmFree( pr );
return;
}
// Mark us as FIRST, MIDDLE, or LAST frag
if( !(tmp & IP_MF) )
dwAux1 |= FRAG_LAST;
else
dwAux1 |= FRAG_MIDDLE;
// Set tmp = data offset
tmp = (tmp & ~IP_MF) * 8;
// If we're over our max, zap it
if( (tmp+(uint)dwAux2) > IP_REASM_MAXSIZE )
{
FragFree( hFrag );
IPReasmFree( pr );
return;
}
// If we're the first frag, then Aux1 is our header size
if( !tmp )
dwAux1 = FRAG_FIRST | (UINT32)hdrlen;
// Else Aux1 is of offset
else
{
dwAux1 |= (UINT32)tmp;
// We also need to remove the IP header from non-first frags
FragGetBufParams( hFrag, 0, &Valid, &Offset );
Offset += hdrlen;
Valid -= hdrlen;
FragSetBufParams( hFrag, Valid, Offset );
}
FragSetAux1( hFrag, dwAux1 );
// Insert hFrag into the correct place in the list
if( !(hFragT = pr->hFrag) )
pr->hFrag = hFrag;
else
{
hFragB = 0;
while( hFragT && FragGetAux1( hFragT ) < dwAux1 )
{
hFragB = hFragT;
hFragT = FragGetNext( hFragB );
}
// We come after B, but before T
FragSetNext( hFrag, hFragT );
if( !hFragB )
pr->hFrag = hFrag;
else
FragSetNext( hFragB, hFrag );
}
// Now see if we have a complete packet
hFrag = pr->hFrag;
// First we must have a "first frag"
dwAux1 = FragGetAux1( hFrag );
if( !(dwAux1 & FRAG_FIRST) )
return;
// dwTmp = Running length (not including IP header)
dwTmp = 0;
while( hFrag )
{
dwAux1 = FragGetAux1( hFrag );
dwAux2 = FragGetAux2( hFrag );
// If this is a "FIRST", then use the largest initial size
if( dwAux1 & FRAG_FIRST )
{
if( dwAux2 > dwTmp )
dwTmp = dwAux2;
}
else
{
// Verify the offset "reaches"
if( (dwAux1&FRAG_OFFSET) > dwTmp )
return;
dwTmp2 = dwTmp - (dwAux1&FRAG_OFFSET); // Data Overlap
if( dwAux2 > dwTmp2 )
{
// Combine this frag into length
dwTmp += dwAux2 - dwTmp2;
}
// If this is the last frag, we're done
if( dwAux1 & FRAG_LAST )
break;
}
hFrag = FragGetNext( hFrag );
}
if( hFrag )
{
// Here we have a completed packet!
// Add in the original IP header size to length
dwTmp += FragGetAux1(pr->hFrag) & FRAG_OFFSET;
// Create the combined packet
hPktIn = IFCreatePacket( (uint)dwTmp, 0, 0 );
if( !hPktIn )
{
// Can't allocate final packet
IPReasmFree( pr );
return;
}
// Get the frag
hFrag = PktGetFrag( hPktIn );
// Get pointers to packet headers
pb = FragGetBufParams( hFrag, 0, 0, 0 );
Offset = PktGetSizeLLC( hPktIn );
// Fixup packet frag info
FragSetBufParams( hFrag, (uint)dwTmp, Offset );
// Now copy the fragments into our combined frag
hFrag = pr->hFrag;
// dwTmp = Running length (not including IP header)
// dwOff = Running offset (length) (including IP header)
dwTmp = 0;
while( hFrag )
{
dwAux1 = FragGetAux1( hFrag );
dwAux2 = FragGetAux2( hFrag );
pbT = FragGetBufParams( hFrag, 0, 0, &OffsetT );
// If this is a "FIRST", then use the largest initial size
if( dwAux1 & FRAG_FIRST )
{
if( dwAux2 > dwTmp )
{
// Special for "first frag" - add in IP header
dwOff = dwAux2+(dwAux1&FRAG_OFFSET);
mmCopy( pb+Offset, pbT+OffsetT, (uint)dwOff );
dwTmp = dwAux2;
}
}
else
{
dwTmp2 = dwTmp - (dwAux1&FRAG_OFFSET); // Data Overlap
if( dwAux2 > dwTmp2 )
{
// Combine this frag into buffer
dwAux2 -= dwTmp2;
mmCopy( pb+Offset+dwOff, pbT+OffsetT+dwTmp2, (uint)dwAux2 );
// Combine this frag into length
dwTmp += dwAux2;
dwOff += dwAux2;
}
// If this is the last frag, we're done
if( dwAux1 & FRAG_LAST )
break;
}
hFrag = FragGetNext( hFrag );
}
// Free the REASM struct and send the packet
ips.dwFragdropped--;
ips.dwReassembled++;
IPReasmFree( pr );
pIpHdr = (IPHDR *)(pb+Offset);
pIpHdr->FlagOff = 0;
pIpHdr->TotalLen = HNC16(((uint)dwOff));
IPChecksum( pIpHdr );
IPRxPacket( hPktIn );
}
return;
}
//--------------------------------------------------------------------
// IPReasmTimeout() - Check reasm list for reassembly timeout
//
//--------------------------------------------------------------------
void IPReasmTimeout()
{
REASM *pr;
REASM *prNext;
UINT32 TimeNow;
TimeNow = llTimerGetTime(0);
prNext = _IPReasmPtr;
while( pr = prNext )
{
prNext = pr->pNext;
if( pr->Timeout < TimeNow )
{
ips.dwFragtimeout++;
IPReasmFree( pr );
}
}
}
//--------------------------------------------------------------------
// IPReasmFree() - Free a reasm entry and bump stats
//
//--------------------------------------------------------------------
void IPReasmFree( REASM *pr )
{
// Remove from chain
if( pr->pNext )
pr->pNext->pPrev = pr->pPrev;
if( !pr->pPrev )
_IPReasmPtr = pr->pNext;
else
pr->pPrev->pNext = pr->pNext;
// Free it
FragFree( pr->hFrag );
ips.dwFragdropped++;
mmFree( pr );
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -