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

📄 ip.c

📁 opentcp_mcf5282原代码
💻 C
字号:
/***************************************************************************************
File:			ip.c

Date:			11.6.2002

Version:		0.1

Author:			Jari Lahti (jari@violasystems.com)

Description:	This file contains functions for processing IP frames received from and
				to be sent to Ethernet

Version Info:	11.6.2002 - First version (JaL)
				22.1.2004 - Port to MCF5282
***************************************************************************************/

#include "opentcp.h"


struct IPFrame ReceivedIPPacket;
struct IPFrame SendIPPacket;

UINT16 IPID;

/********************************************************************************
Function:		ProcessIPIn

Parameters:		struct otcp_ethframe* frame - pointer to received frame structure

Return val:		INT16 - (-1) Not OK
						>0 Length of next layer data (Packet OK)


Date:			11.6.2002

Desc:			Check received IP Frame if it's OK to sent it to upper layers
*********************************************************************************/

INT16 ProcessIPIn (struct otcp_ethframe* frame)
{

	UINT8 olen;
	UINT8 i;

	/* Check for Protocol								*/

	DEBUGOUT("Checking if IP Protocol\n\r");

	if( frame->protocol != PROTOCOL_IP )
		return(-1);


	DEBUGOUT("It's IP\n\r");

	if( frame->framesize < ETH_HEADER_LEN )
		return(-1);

	if( (frame->framesize - ETH_HEADER_LEN) < IP_HLEN )
		return(-1);

	/* Get IP Header Information						*/

	NETWORK_RECEIVE_INITIALIZE(frame->bufindex);

	ReceivedIPPacket.vihl = RECEIVE_NETWORK_B();

	/* Is it IPv4?	*/

	if( (ReceivedIPPacket.vihl & 0xF0) != 0x40 )
	{
		DEBUGOUT("ERROR: IP is not version 4!\n\r");
		return(-1);
	}

	DEBUGOUT("IP Version 4 OK!\n\r");

	ReceivedIPPacket.tos = RECEIVE_NETWORK_B();

	ReceivedIPPacket.tlen = RECEIVE_NETWORK_B();
	ReceivedIPPacket.tlen <<= 8;
	ReceivedIPPacket.tlen |= RECEIVE_NETWORK_B();

	ReceivedIPPacket.id = RECEIVE_NETWORK_B();
	ReceivedIPPacket.id <<= 8;
	ReceivedIPPacket.id |= RECEIVE_NETWORK_B();

	ReceivedIPPacket.frags = RECEIVE_NETWORK_B();
	ReceivedIPPacket.frags <<= 8;
	ReceivedIPPacket.frags |= RECEIVE_NETWORK_B();

	ReceivedIPPacket.ttl= RECEIVE_NETWORK_B();

	ReceivedIPPacket.protocol= RECEIVE_NETWORK_B();

	ReceivedIPPacket.checksum = RECEIVE_NETWORK_B();
	ReceivedIPPacket.checksum <<= 8;
	ReceivedIPPacket.checksum |= RECEIVE_NETWORK_B();

	ReceivedIPPacket.sip = RECEIVE_NETWORK_B();
	ReceivedIPPacket.sip <<= 8;
	ReceivedIPPacket.sip |= RECEIVE_NETWORK_B();
	ReceivedIPPacket.sip <<= 8;
	ReceivedIPPacket.sip |= RECEIVE_NETWORK_B();
	ReceivedIPPacket.sip <<= 8;
	ReceivedIPPacket.sip |= RECEIVE_NETWORK_B();

	ReceivedIPPacket.dip = RECEIVE_NETWORK_B();
	ReceivedIPPacket.dip <<= 8;
	ReceivedIPPacket.dip |= RECEIVE_NETWORK_B();
	ReceivedIPPacket.dip <<= 8;
	ReceivedIPPacket.dip |= RECEIVE_NETWORK_B();
	ReceivedIPPacket.dip <<= 8;
	ReceivedIPPacket.dip |= RECEIVE_NETWORK_B();

	/* Is that packet for us?			*/

	if( (ReceivedIPPacket.dip != localmachine.localip) &&
		(ReceivedIPPacket.dip != IP_BROADCAST_ADDRESS)	 )
	{
		/* It's not for us. Check still if ICMP with rigth physical	*/
		/* address that migth be used to set temporary IP			*/

		DEBUGOUT("IP address does not match!\n\r");

		if( ReceivedIPPacket.protocol != IP_ICMP)
			return(-1);

		/* Check physical address			*/

		for(i=0; i<PHY_ADR_LEN; i++)
		{
			if(frame->destination[i] != localmachine.localHW[i])
				return(-1);
		}

	}


	/* Is there options to copy?		*/

	olen = ReceivedIPPacket.vihl & 0x0F;
	olen <<= 2;
	olen -= IP_MIN_HLEN;

	/* Somebody bluffing with too long option field?	*/

	if(olen > MAX_IP_OPTLEN)
	{
		DEBUGOUT("ERROR:Size of maximum allowed IP option lengt exceeded!\n\r");
		return(-1);
	}

	if( olen > (frame->framesize - ETH_HEADER_LEN - IP_HLEN) )
	{
		DEBUGOUT("ERROR:IP option field too long!\n\r");
		return(-1);
	}

	for( i=0; i < olen; i++ )
	{
		ReceivedIPPacket.opt[i] = RECEIVE_NETWORK_B();
		DEBUGOUT("IP Options..\n\r");
	}

	if(ReceivedIPPacket.tlen >  (frame->framesize - ETH_HEADER_LEN) )
	{
		DEBUGOUT("ERROR: Total len too long\r\n");
		return(-1);
	}

	/* Is the checksum OK?	*/

	DEBUGOUT("Validating the IP checksum..\n\r");

	if ( IP_CheckCS(&ReceivedIPPacket) != TRUE )
	{
		DEBUGOUT("IP Checksum Corrupted..\n\r");
		return(-1);
	}

	DEBUGOUT("..Checksum OK!\n\r");

	/* Add the address to ARP cache	*/

	if( ReceivedIPPacket.sip != IP_BROADCAST_ADDRESS)
		arpadd( ReceivedIPPacket.sip, &frame->source[0], ARP_TEMP_IP);

	/* Calculate the start of next layer data	*/

	ReceivedIPPacket.BufIndex = frame->bufindex + IP_HLEN + olen;

	/* Is this packet fragmented?						*/
	/* We don't deal with those							*/
	/* TODO: Implement Stub handler for more mem. uP's	*/

	if( ReceivedIPPacket.frags & IP_MOREFRAGS )
	{
		DEBUGOUT("Fragmented IP packet\r\n");
		return(-1);
	}

	if( ReceivedIPPacket.frags & IP_FRAGOFF )
	{
		DEBUGOUT("Fragmented IP packet\r\n");
		return(-1);
	}


	DEBUGOUT("Leaving IP succesfully..\n\r");

	/* Return the legth left for next layers	*/

	if( (ReceivedIPPacket.tlen - IP_HLEN - olen) == 20 )
	{
		DEBUGOUT("20 bytes to next layer\r\n");
	}
	else if( (ReceivedIPPacket.tlen - IP_HLEN - olen) > 20 )
	{
		DEBUGOUT("Over 20 bytes to next layers\r\n");
	}
	else
	{
		DEBUGOUT("Less than 20 bytes to next layer\r\n");
	}

	return(ReceivedIPPacket.tlen - IP_HLEN - olen);

}


/********************************************************************************
Function:		ProcessIPOut

Parameters:		UINT32 ipadr - remote IP address
				UINT8  pcol - protocol over IP
				UINT8  tos - type of service required
				UINT8  ttl - time to live for IP packet
				UINT8* dat - pointer to data buffer
				UINT16 len - legth of data

Return val:		INT16 - (-1) Not OK (General)
						(-2) ARP cache not ready
						>0 Number of data bytes sent (Packet OK)


Date:			17.6.2002

Desc:			Try to send out the IP frame
*********************************************************************************/

INT16 ProcessIPOut (UINT32 ipadr, UINT8 pcol, UINT8 tos, UINT8 ttl, UINT8* dat, UINT16 len)
{
	struct arpentry *qstruct;
	UINT16 i;


	/* Try to get MAC address from ARP cache	*/

	qstruct = arpfind(ipadr, &localmachine, ARP_TEMP_IP);

	if( qstruct == 0 )		/* Not ready yet	*/
		return(-2);

	/* Select network buffer						*/
	/* TODO: This network related stuff should 		*/
	/* be moved and abstracted to Ethernet layer	*/

	switch(pcol)
	{
		case IP_ICMP:

			NETWORK_SEND_INITIALIZE(TXBUF_ENET);
			DEBUGOUT("Assembling IP packet to ICMP buffer\n\r");

			break;

		case IP_UDP:

			NETWORK_SEND_INITIALIZE(TXBUF_ENET);
			DEBUGOUT("Assembling IP packet to UDP buffer\n\r");

			break;

		case IP_TCP:

			NETWORK_SEND_INITIALIZE(TXBUF_ENET);
			DEBUGOUT("Assembling IP packet to TCP buffer\n\r");

			break;

		default:			/* Unknown protocol	*/
			return(-1);
	}

	/* Fill the Ethernet information	*/

	for( i=0; i<MAXHWALEN; i++)
	{
		otcp_txframe.destination[i] = qstruct->hwadr[i];
	}

	for( i=0; i<MAXHWALEN; i++)
	{
		otcp_txframe.source[i] = localmachine.localHW[i];
	}

	otcp_txframe.protocol = PROTOCOL_IP;

	NETWORK_ADD_DATALINK(&otcp_txframe);

	/* Construct the IP header	*/

	SendIPPacket.vihl = IP_DEF_VIHL;

	if(tos != 0)
		SendIPPacket.tos = tos;
	else
		SendIPPacket.tos = localmachine.tos;

	SendIPPacket.tlen = IP_HLEN + len;
	SendIPPacket.id = IPID++;
	SendIPPacket.frags = 0;
	SendIPPacket.ttl = ttl;
	SendIPPacket.protocol = pcol;
	SendIPPacket.checksum = 0;
	SendIPPacket.sip = localmachine.localip;
	SendIPPacket.dip = ipadr;

	/* Calculate checksum for the IP header	*/

	SendIPPacket.checksum = IP_ConstructCS( &SendIPPacket );

	/* Assemble bytes to network	*/

	SEND_NETWORK_B(SendIPPacket.vihl);
	SEND_NETWORK_B(SendIPPacket.tos);
	SEND_NETWORK_B( (UINT8)(SendIPPacket.tlen >> 8) );
	SEND_NETWORK_B( (UINT8)SendIPPacket.tlen );
	SEND_NETWORK_B( (UINT8)(SendIPPacket.id >> 8) );
	SEND_NETWORK_B( (UINT8)SendIPPacket.id );
	SEND_NETWORK_B( (UINT8)(SendIPPacket.frags >> 8) );
	SEND_NETWORK_B( (UINT8)SendIPPacket.frags );
	SEND_NETWORK_B(SendIPPacket.ttl);
	SEND_NETWORK_B(SendIPPacket.protocol);
	SEND_NETWORK_B( (UINT8)(SendIPPacket.checksum >> 8) );
	SEND_NETWORK_B( (UINT8)SendIPPacket.checksum );
	SEND_NETWORK_B( (UINT8)(SendIPPacket.sip >> 24) );
	SEND_NETWORK_B( (UINT8)(SendIPPacket.sip >> 16) );
	SEND_NETWORK_B( (UINT8)(SendIPPacket.sip >> 8) );
	SEND_NETWORK_B( (UINT8)SendIPPacket.sip );
	SEND_NETWORK_B( (UINT8)(SendIPPacket.dip >> 24) );
	SEND_NETWORK_B( (UINT8)(SendIPPacket.dip >> 16) );
	SEND_NETWORK_B( (UINT8)(SendIPPacket.dip >> 8) );
	SEND_NETWORK_B( (UINT8)SendIPPacket.dip );

	/* Assemble data	*/

	SEND_NETWORK_BUF(dat, len);

	/* Launch it		*/

	NETWORK_COMPLETE_SEND( SendIPPacket.tlen );

	return(len);


}

/********************************************************************************
Function:		IP_ConstructCS

Parameters:		struct IPFrame* frame - pointer to IP frame to be checked


Return val:		UINT32 - calculated checksum


Date:			8.7.2002

Desc:			Calculate checksum for given IP header
*********************************************************************************/

UINT32 IP_ConstructCS (struct IPFrame* frame)
{
	UINT16 ip_cs;
	UINT8 cs_cnt;
	UINT8 olen;
	UINT8 i;

	ip_cs = 0;
	cs_cnt = 0;

	ip_cs = IpCheckSum(ip_cs, frame->vihl, cs_cnt++);
	ip_cs = IpCheckSum(ip_cs, frame->tos, cs_cnt++);
	ip_cs = IpCheckSum(ip_cs, (UINT8)(frame->tlen >> 8), cs_cnt++);
	ip_cs = IpCheckSum(ip_cs, (UINT8)frame->tlen, cs_cnt++);
	ip_cs = IpCheckSum(ip_cs, (UINT8)(frame->id >> 8), cs_cnt++);
	ip_cs = IpCheckSum(ip_cs, (UINT8)frame->id, cs_cnt++);
	ip_cs = IpCheckSum(ip_cs, (UINT8)(frame->frags >> 8), cs_cnt++);
	ip_cs = IpCheckSum(ip_cs, (UINT8)frame->frags, cs_cnt++);
	ip_cs = IpCheckSum(ip_cs, frame->ttl, cs_cnt++);
	ip_cs = IpCheckSum(ip_cs, frame->protocol, cs_cnt++);
	ip_cs = IpCheckSum(ip_cs, (UINT8)(frame->sip >> 24), cs_cnt++);
	ip_cs = IpCheckSum(ip_cs, (UINT8)(frame->sip >> 16), cs_cnt++);
	ip_cs = IpCheckSum(ip_cs, (UINT8)(frame->sip >> 8), cs_cnt++);
	ip_cs = IpCheckSum(ip_cs, (UINT8)frame->sip, cs_cnt++);
	ip_cs = IpCheckSum(ip_cs, (UINT8)(frame->dip >> 24), cs_cnt++);
	ip_cs = IpCheckSum(ip_cs, (UINT8)(frame->dip >> 16), cs_cnt++);
	ip_cs = IpCheckSum(ip_cs, (UINT8)(frame->dip >> 8), cs_cnt++);
	ip_cs = IpCheckSum(ip_cs, (UINT8)frame->dip, cs_cnt++);

	/* Is there options?				*/

	olen = frame->vihl & 0x0F;
	olen <<= 2;
	olen -= IP_MIN_HLEN;

	for( i=0; i<olen; i++)
		ip_cs = IpCheckSum(ip_cs, (UINT8)frame->opt[i], cs_cnt++);

	/* Take complement	*/

	ip_cs = ~ ip_cs;

	return(ip_cs);

}


/********************************************************************************
Function:		IP_CheckCS

Parameters:		struct IPFrame* frame - pointer to IP frame to be checked


Return val:		UINT8 0 - Checksum corrupted
				UINT8 1 - Checksum OK

Date:			12.6.2002

Desc:			Calculate if the IP frame header CS is not corrupted. May be
				made more intelligent/faster by using carry method.
*********************************************************************************/

UINT8 IP_CheckCS (struct IPFrame* frame)
{
	UINT16 ip_cs;
	UINT8 cs_cnt;
	UINT8 olen;
	UINT8 i;

	ip_cs = 0;
	cs_cnt = 0;

	ip_cs = IpCheckSum(ip_cs, frame->vihl, cs_cnt++);
	ip_cs = IpCheckSum(ip_cs, frame->tos, cs_cnt++);
	ip_cs = IpCheckSum(ip_cs, (UINT8)(frame->tlen >> 8), cs_cnt++);
	ip_cs = IpCheckSum(ip_cs, (UINT8)frame->tlen, cs_cnt++);
	ip_cs = IpCheckSum(ip_cs, (UINT8)(frame->id >> 8), cs_cnt++);
	ip_cs = IpCheckSum(ip_cs, (UINT8)frame->id, cs_cnt++);
	ip_cs = IpCheckSum(ip_cs, (UINT8)(frame->frags >> 8), cs_cnt++);
	ip_cs = IpCheckSum(ip_cs, (UINT8)frame->frags, cs_cnt++);
	ip_cs = IpCheckSum(ip_cs, frame->ttl, cs_cnt++);
	ip_cs = IpCheckSum(ip_cs, frame->protocol, cs_cnt++);
	ip_cs = IpCheckSum(ip_cs, (UINT8)(frame->checksum >> 8), cs_cnt++);
	ip_cs = IpCheckSum(ip_cs, (UINT8)frame->checksum, cs_cnt++);
	ip_cs = IpCheckSum(ip_cs, (UINT8)(frame->sip >> 24), cs_cnt++);
	ip_cs = IpCheckSum(ip_cs, (UINT8)(frame->sip >> 16), cs_cnt++);
	ip_cs = IpCheckSum(ip_cs, (UINT8)(frame->sip >> 8), cs_cnt++);
	ip_cs = IpCheckSum(ip_cs, (UINT8)frame->sip, cs_cnt++);
	ip_cs = IpCheckSum(ip_cs, (UINT8)(frame->dip >> 24), cs_cnt++);
	ip_cs = IpCheckSum(ip_cs, (UINT8)(frame->dip >> 16), cs_cnt++);
	ip_cs = IpCheckSum(ip_cs, (UINT8)(frame->dip >> 8), cs_cnt++);
	ip_cs = IpCheckSum(ip_cs, (UINT8)frame->dip, cs_cnt++);

	/* Is there options?				*/

	olen = frame->vihl & 0x0F;
	olen <<= 2;
	olen -= IP_MIN_HLEN;

	for( i=0; i<olen; i++)
		ip_cs = IpCheckSum(ip_cs, (UINT8)frame->opt[i], cs_cnt++);

	/* Analyze the result	*/

	ip_cs = ~ ip_cs;

	if(ip_cs == IP_GOOD_CS)
		return 1;

	/* Fuck, it failed!	*/

	return 0;


}

/********************************************************************************
Function:		IpCheckSum

Parameters:		UINT16 cs - last checksum value
				UINT8 dat - byte to be added to checksum
				UINT8 count - is this byte MSB or LSB

Return val:		UINT16 - new checksum value


Date:			24.2.2002

Desc:			Add one given byte to given checksum and return the new
				checksum value
*********************************************************************************/

UINT16 IpCheckSum (UINT16 cs, UINT8 dat, UINT8 count)
{
	UINT8 b = dat;
	UINT8 Cs_L;
	UINT8 Cs_H;

	Cs_H = (UINT8)(cs >> 8);
	Cs_L = (UINT8)cs;

	if( count & 0x01 )
	{
		/* We are processing LSB	*/

		if( (Cs_L = Cs_L + b) < b )
		{
			if( ++Cs_H == 0 )
				Cs_L++;
		}

	}
	else
	{
		/* We are processing MSB	*/

		if( (Cs_H = Cs_H + b) < b )
		{
			if( ++Cs_L == 0 )
				Cs_H++;
		}
	}

	return( ( (UINT16)Cs_H << 8 ) + Cs_L);



}


/********************************************************************************
Function:		IpCheckSumBuf

Parameters:		UINT16 cs - last checksum value
				UINT8* buf - buffer checksummed
				UINT16 len - length of data

Return val:		UINT16 - new checksum value


Date:			4.4.2003

Desc:			Calculates CS to buffer and return the new
				checksum value.
*********************************************************************************/

UINT32 IpCheckSumBuf (UINT16 cs, UINT8* buf, UINT16 len)
{
	UINT16 dat;
	UINT32 temp;

	temp = cs;

	while(len>1)
	{
		len -= 2;
		dat = *buf++;
		dat <<= 8;
		dat |= *buf++;
		temp += dat;
	}

	temp = (temp >> 16) + (temp & 0xFFFF);	/* Add in carry		*/
	temp += (temp >>16);					/* Maybe one more	*/

	if(len)
		temp = IpCheckSum(temp, *buf, 0);

	return( (UINT16) temp );

}

⌨️ 快捷键说明

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