📄 icmpin.c
字号:
//--------------------------------------------------------------------------
// Ip Stack
//--------------------------------------------------------------------------
// ICMPIN.C
//
// Routines receving ICMP packets
//
//
// Author: Michael A. Denio
// Copyright 1999 by Texas Instruments Inc.
//-------------------------------------------------------------------------
#include <stkmain.h>
static void ICMPRevSrcRoute( uint IPHdrLen, IPHDR *pbHdrIP );
//--------------------------------------------------------------------
// ICMPInput()
//
// Rx ICMP Packet
//--------------------------------------------------------------------
void ICMPInput( HANDLE hPkt )
{
HANDLE hFrag;
uint w,Offset,Valid,IPHdrLen,ICMPLen;
IPN IPSrc,IPDst;
uint Type,Code;
UINT8 *pb;
IPHDR *pIpHdr;
ICMPHDR *pIcHdr;
if( !(hFrag = PktGetFrag( hPkt )) )
{
DbgPrintf(DBG_ERROR,"ICMPRxPacket: No packet");
PktFree( hPkt );
return;
}
// Get the size of the IP Header and pointer to our data
w = PktGetFlags( hPkt );
if( !(w & FLG_PKT_IP_VALID) || (w & FLG_PKT_LLC_VALID) )
{
DbgPrintf(DBG_ERROR,"ICMPRxPacket: Bad packet");
PktFree( hPkt );
return;
}
// Get the IP header len
IPHdrLen = PktGetSizeNet( hPkt );
// Get the buffer parameters
pb = FragGetBufParams( hFrag, 0, &Valid, &Offset );
// Assign an IP header pointer
pIpHdr = (IPHDR *)(pb + Offset);
// Assign a ICMP header pointer
pIcHdr = (ICMPHDR *)(pb + Offset + IPHdrLen);
// Get the total length of the ICMP message
ICMPLen = (uint)(HNC16( pIpHdr->TotalLen )) - IPHdrLen;
// Check for packet too small
if( ICMPLen < ICMPHDR_SIZE )
{
_dwICMPInErrors++;
PktFree( hPkt );
return;
}
// Check checksum
w = (uint)pIcHdr->Checksum;
ICMPChecksum( pIcHdr, ICMPLen );
if( w != (uint)pIcHdr->Checksum )
{
_dwICMPInErrors++;
PktFree( hPkt );
return;
}
// Check for bad type
Type = (uint)pIcHdr->Type;
Code = (uint)pIcHdr->Code;
if( Type > ICMP_MAXTYPE )
{
_dwICMPInErrors++;
PktFree( hPkt );
return;
}
// Record the Transport Header Size
PktSetSizeTP( hPkt, ICMPLen );
PktSetFlagsSet( hPkt, FLG_PKT_TP_VALID );
// Bump the stats
_dwICMPIn[ Type ]++;
// Get source and destination
IPSrc = RdNet32(&pIpHdr->dwIPSrc);
IPDst = RdNet32(&pIpHdr->dwIPDst);
// Process the Message
switch( Type )
{
case ICMP_UNREACH:
switch (Code)
{
case ICMP_UNREACH_NET:
case ICMP_UNREACH_HOST:
case ICMP_UNREACH_PROTOCOL:
case ICMP_UNREACH_PORT:
case ICMP_UNREACH_SRCFAIL:
Code += PRC_UNREACH_NET;
break;
case ICMP_UNREACH_NEEDFRAG:
Code = PRC_MSGSIZE;
break;
case ICMP_UNREACH_NET_UNKNOWN:
case ICMP_UNREACH_NET_PROHIB:
case ICMP_UNREACH_TOSNET:
Code = PRC_UNREACH_NET;
break;
case ICMP_UNREACH_HOST_UNKNOWN:
case ICMP_UNREACH_ISOLATED:
case ICMP_UNREACH_HOST_PROHIB:
case ICMP_UNREACH_TOSHOST:
Code = PRC_UNREACH_HOST;
break;
case ICMP_UNREACH_FILTER_PROHIB:
case ICMP_UNREACH_HOST_PRECEDENCE:
case ICMP_UNREACH_PRECEDENCE_CUTOFF:
Code = PRC_UNREACH_PORT;
break;
default:
goto bad_code;
}
goto deliver;
case ICMP_TIMXCEED:
if( Code > 1 )
goto bad_code;
Code += PRC_TIMXCEED_INTRANS;
goto deliver;
case ICMP_PARAMPROB:
if( Code > 1 )
goto bad_code;
Code = PRC_PARAMPROB;
goto deliver;
case ICMP_SOURCEQUENCH:
if( Code )
goto bad_code;
Code = PRC_QUENCH;
deliver:
SockPcbCtlError( Code, (IPHDR *)(pIcHdr->Data + 4) );
break;
bad_code:
break;
case ICMP_REDIRECT:
if( Code > 3 )
goto bad_code;
// Handle Route Change Immediately
pIpHdr = (IPHDR *)(pIcHdr->Data + 4);
// IPSrc is the route we're trying to get to
IPSrc = RdNet32(&pIpHdr->dwIPDst);
// IPDst is the gatway we should be uisng
IPDst = RdNet32(((IPN *)(pIcHdr->Data)));
// Redirect route if option is set
if( ICMP_DO_REDIRECT )
{
RtRedirect( IPSrc, IPDst );
SockPcbCtlError(PRC_REDIRECT_NET+Code, (IPHDR *)(pIcHdr->Data+4));
}
// Lastly, send a report
RTCReport( MSG_RTC_REDIRECT, IPSrc, IPDst );
break;
// Echo Request
case ICMP_ECHO:
// If this packet is for us, reflect it
if( BindFindByHost( 0, IPDst ) )
goto ICMP_REFLECT;
// The following are just sent to Raw
case ICMP_ECHOREPLY:
case ICMP_ROUTERADVERT:
case ICMP_ROUTERSOLICIT:
case ICMP_TSTAMPREPLY:
case ICMP_IREQREPLY:
case ICMP_MASKREPLY:
default:
break;
}
// Give most packets to Raw
RawInput( hPkt );
return;
ICMP_REFLECT:
// Don't forward back to bad address
if( IPSrc == INADDR_ANY || IPSrc == INADDR_BROADCAST ||
IN_EXPERIMENTAL(IPSrc) || IN_MULTICAST(IPSrc) ||
IN_LOOPBACK(IPSrc) )
{
PktFree( hPkt );
return;
}
// Fix the TTL
pIpHdr->Ttl = ICMP_TTL_ECHO;
// Change the type to reply
pIcHdr->Type = ICMP_ECHOREPLY;
// Bump the stats
_dwICMPOut[ ICMP_ECHOREPLY ]++;
// Swap Src and Dst
// The Old Src is now the Dst
WrNet32( &pIpHdr->dwIPSrc, IPDst );
WrNet32( &pIpHdr->dwIPDst, IPSrc );
// Checksum the reply
ICMPChecksum( pIcHdr, ICMPLen );
// Now we must reverse the source route (if any)
if( IPHdrLen > IPHDR_SIZE )
ICMPRevSrcRoute( IPHdrLen, pIpHdr );
// Send the packet
IPTxPacket( hPkt, FLG_IPTX_RAW );
return;
}
//--------------------------------------------------------------------
// ICMPRevSrcRoute()
//
// Reverse the source route of a packet
//--------------------------------------------------------------------
static void ICMPRevSrcRoute( uint IPHdrLen, IPHDR *pIpHdr )
{
uint OptIdx,OptBytes,OptSize;
UINT8 Opt;
int OffFirst,OffLast;
IPN IPTmp;
// Byte count of options
OptBytes = IPHdrLen - IPHDR_SIZE;
// Process option bytes
for( OptIdx = 0; OptIdx < OptBytes; OptIdx += OptSize )
{
Opt = pIpHdr->Options[OptIdx];
// Validate Option and Get Size
if( Opt == IPOPT_EOL )
break;
else if( Opt == IPOPT_NOP )
OptSize = 1;
else
{
OptSize = pIpHdr->Options[OptIdx+1];
if( OptSize <= 0 || OptSize > OptBytes )
return;
}
// Check for source routing
if( Opt == IPOPT_SSRR || Opt == IPOPT_LSRR )
{
// Source route in use. We must reverse it.
// First, set Offset to 4
pIpHdr->Options[OptIdx+2] = 4;
// Now reverse the route
OffFirst = OptIdx+3;
OffLast = OptIdx+OptSize-4;
// We know the DestIP is now the last thing in the source
// route, and what was last in the source route is now
// DestIP
mmCopy( &IPTmp, pIpHdr->Options+OffLast, 4 );
mmCopy( pIpHdr->Options+OffLast, &pIpHdr->dwIPDst, 4 );
mmCopy( &pIpHdr->dwIPDst, &IPTmp, 4 );
// We've used OffLast, so bump it down
OffLast -= 4;
// Now, while OffFirst < OffLast, do SWAPS.
while( OffFirst < OffLast )
{
mmCopy( &IPTmp, pIpHdr->Options+OffLast, 4 );
mmCopy( pIpHdr->Options+OffLast, pIpHdr->Options+OffFirst, 4 );
mmCopy( pIpHdr->Options+OffFirst, &IPTmp, 4 );
OffFirst += 4;
OffLast -= 4;
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -