📄 ipin.c
字号:
//--------------------------------------------------------------------------
// Ip Stack
//--------------------------------------------------------------------------
// IPIN.C
//
// Routines related to IP Receive
//
//
// Author: Michael A. Denio
// Copyright 1999 by Texas Instruments Inc.
//-------------------------------------------------------------------------
#include <stkmain.h>
#include "ip.h"
static IPN _IPFltAddr = 0;
static IPN _IPFltMask = 0;
//--------------------------------------------------------------------
// IPFilterSet() - Set IP Filtered Net
//
// The stack has the ability to protect one network (which can be
// a combination of multiple networks). The IP address and mask is
// set by this function. The feature is enabled via a configuration
// entry.
//--------------------------------------------------------------------
void IPFilterSet( IPN IPAddr, IPN IPMask )
{
_IPFltAddr = IPAddr & IPMask;
_IPFltMask = IPMask;
}
//--------------------------------------------------------------------
// IPRouteIP() - Find Route's Outgoing IP
//
// Return the IP address of the outgoing IF for a packet routed
// to the IP address supplied in IPDst. The Source IP is provided
// in the event that the Dest IP does not contain any relevant
// information (e.g.: broadcast or multicast).
//--------------------------------------------------------------------
static IPN IPRouteIP( HANDLE hIF, IPN IPDst, IPN IPSrc, uint Opt )
{
HANDLE hRt;
IPN IPOut;
// This function will potentially have to examine routes, but
// we'll try the easy cases first.
// Anything sent via a local IF (NULL) can be looked up by IPDst
// We know this since it is the only way a NULL IF packet could
// have got this far.
if( !hIF )
{
// Try and verify the local IP host address. Otherwise,
// we'll just use the IPDst. Note that we punt if we
// don't verify the IP. We don't use IPSrc because we know
// the packet came from another local IF. Therefore, the
// IPSrc doesn't reperesent the IP subnet of the outgoing
// interface.
if( !(IPOut = BindIFNet2IPHost( hIF, IPDst )) )
return( IPDst );
return( IPOut );
}
// We take the following packets:
// - The Dst is an all 0's BCast
// - The Dst is an all 1's BCast
// - The Dst is a Multicast Addr
// - The Dst is one of our host addresses
// Do BCast and Multicast First
if( IPDst == INADDR_ANY || IPDst == INADDR_BROADCAST ||
IN_MULTICAST(IPDst) )
{
// The packet is ours, but we don't have a sub-net to lookup
// our IF's IP address. First, we'll try and find one based
// in the IPNet of the source
if( !(IPOut = BindIFNet2IPHost( hIF, IPSrc )) )
{
// Oops, now we're not sure of the true dest - we'll
// simply return anything we find on hIF
IPOut = BindIF2IPHost( hIF );
}
return( IPOut );
}
// See if this packet is addressed directly to us
if( BindFindByHost( 0, IPDst ) )
return( IPDst );
// This is a routed packet (not for us). If forwarding is off,
// there is no reason to go on.
if( !IP_FORWARDING )
return( 0 );
// Now find the next hop for this packet. Search for a route
// WITHOUT cloning. All we need from the route is the outgoing
// IF / IP.
if( !(hRt = IPGetRoute( FLG_RTF_REPORT, IPDst, Opt )) )
return(0);
// We have a viable route for the packet. Now, get the IP host
// address of the outgoing IF on the IP subnet of the next hop.
// We can look up the IP of the outgoing IF directly.
IPOut = BindIFNet2IPHost( RtGetIF(hRt), RtGetIPAddr(hRt) );
RtDeRef( hRt );
// Note: Sometimes IPOut will be NULL!
// IPOut == NULL is an odd case. What happens is
// that we have a route for a host for which we don't
// have a network! This can only be caused by an illegal
// host, or by a misconfiguration. Since we have no
// outgoing IP for this IF/Host, we're forced to
// return NULL.
return( IPOut );
}
//--------------------------------------------------------------------
// IPRxPacket( HANDLE hPkt )
//
// Processes message containing a newly received IP packet
//--------------------------------------------------------------------
void IPRxPacket( HANDLE hPkt )
{
HANDLE hFrag,hIFRx;
uint w,Offset,Valid,IPHdrLen,SrcRoute;
uint PktFlags;
UINT8 *pb;
IPHDR *pIpHdr;
IPN IPDst,IPSrc,IPTmp;
#ifdef _INCLUDE_NAT_CODE
int NatRC;
#endif
// If not executing, then no frame gets through
if( !_IPExecuting )
{
PktFree( hPkt );
return;
}
// Get the frag for this packet
if( !(hFrag = PktGetFrag( hPkt )) )
{
DbgPrintf(DBG_ERROR,"IPRxPacket: No frag");
PktFree( hPkt );
return;
}
// Get the the receiving interface
hIFRx = PktGetIFRx( hPkt );
// Get the buffer parameters
pb = FragGetBufParams( hFrag, 0, &Valid, &Offset );
// We don't ever use the LLC
PktFlags = PktGetFlags( hPkt );
if( PktFlags & FLG_PKT_LLC_VALID )
{
// Get offset to our data
w = PktGetSizeLLC( hPkt );
Offset += w;
Valid -= w;
// Patch the LLC out of the packet
FragSetBufParams( hFrag, Valid, Offset );
PktSetFlagsClear( hPkt, FLG_PKT_LLC_VALID );
}
// Assign a IP header pointer
pIpHdr = (IPHDR *)(pb + Offset);
// Bump Rx Count
ips.dwTotal++;
// We only handle IP version 4
if( (pIpHdr->VerLen & 0xf0) != 0x40 )
{
ips.dwBadvers++;
PktFree( hPkt );
return;
}
// Make sure size is in range and not bigger than the packet length
if( (IPHdrLen = ((pIpHdr->VerLen & 0xf)*4) ) < IPHDR_SIZE ||
IPHdrLen > Valid )
{
ips.dwBadhlen++;
PktFree( hPkt );
return;
}
// Make sure total length is reasonable, and not bigger than the
// packet length
w = (uint)pIpHdr->TotalLen;
if( HNC16(w) > Valid )
{
ips.dwBadlen++;
PktFree( hPkt );
return;
}
// Record the length for others
PktSetSizeNet( hPkt, IPHdrLen );
PktSetFlagsSet( hPkt, FLG_PKT_IP_VALID );
// Verify the IP header checksum
w = (uint)pIpHdr->Checksum;
IPChecksum( pIpHdr );
if( w != (uint)pIpHdr->Checksum )
{
ips.dwBadsum++;
PktFree( hPkt );
return;
}
// Record the Destination and Source IP
IPDst = RdNet32( &pIpHdr->dwIPDst );
IPSrc = RdNet32( &pIpHdr->dwIPSrc );
// Initially assume no source routing
SrcRoute = 0;
//
// Process any IP Options
//
if( IPHdrLen > IPHDR_SIZE )
{
uint OptIdx,OptBytes,OptSize;
UINT8 Opt;
// 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 )
{
// This is an ICMP error
// Give the whole works to ICMP
ips.dwBadoptions++;
w = IPHDR_SIZE + OptIdx + 1;
ICMPGenPacket( pIpHdr, hIFRx, ICMP_PARAMPROB, w, 0 );
PktFree( hPkt );
return;
}
}
// Check for legal opiton offset on RECORD ROUTE variants
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -