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

📄 ip layer.c

📁 单片机TCP IP software
💻 C
字号:
//=================================================================================
/*

	本单元实现IP层协议,包含接受和发送两个通路。

	接受通路:被链路层RTL8019AS单元,在接收到数据包之后调用。
		分析后,如果是ARP或者RARP协议,则就在本单元内处理。
				如果是TCP/UDP协议,则提交给TCPUDP Layer处理。

*/
//=================================================================================



//=================================================================================
#include	"TCPIP_Protocol.h"
#include	"RTL8019AS.h"
#include	"App_Layer.h"
//=================================================================================



//	外部定义的常量
//=================================================================================
extern	const	struct	TMAC	cMAC_Board;
extern	const	struct	TMAC	cMAC_Self;
extern	unsigned short	vIP_DataBuf[];
//=================================================================================



//=================================================================================
struct	TIPAddr	vIP_SelfIP = {0xC0A8,0x14C0};

//union	TPacketHeader vIP_PktHeader;

//	IP->MAC对应表
#define	cIP_IPMACTableSize	10
struct	TIP_MAC_Table	vIP_IPMACTable[cIP_IPMACTableSize];
short	vIP_IPMACTablePointer;
unsigned short vIP_IPID;
//=================================================================================




//	内部的函数
//=================================================================================
void	IP_ARPPacketReceived(unsigned short * pDataPacket);
void	IP_DealWith_ICMP(unsigned short* pHeader, unsigned short* pPacket, unsigned short PacketLength);
void	IP_DealWith_IGMP(unsigned short* pHeader, unsigned short* pPacket, unsigned short PacketLength);
void	IP_DealWith_UDP(unsigned short*	pHeader, unsigned short* pPacket, unsigned short PacketLength);
void	IP_DealWith_TCP(unsigned short*	pHeader, unsigned short* pPacket, unsigned short PacketLength);
void	IP_PingResponse(unsigned short * pHeader, short	PacketLength);
void	IP_SendUDP(struct TClientInfo Client, short DataLength); 
unsigned short IP_ChkSum(unsigned short* pData,	unsigned short PacketLength);
//=================================================================================


//=================================================================================
void	IP_Init()
{
	short	i;
	vIP_IPMACTablePointer =	0;
	for(i=0; i<cIP_IPMACTableSize; i++)
	{
		vIP_IPMACTable[i].ip.Addr2_1	= 0;
		vIP_IPMACTable[i].ip.Addr4_3	= 0;
		vIP_IPMACTable[i].MAC.Addr2_1	= 0;
		vIP_IPMACTable[i].MAC.Addr4_3	= 0;
		vIP_IPMACTable[i].MAC.Addr6_5	= 0;
	}
	vIP_IPID = 0;
}
//=================================================================================






//	IP数据包分发程序,根据数据包的类型,决定使用何种函数进行处理。
//=================================================================================
void	IP_DispatchPacket(unsigned short * pData)
{
	struct	TMACHeader * pMACHdr;
	struct	TIPHeader * pIPHdr;
	unsigned short UDPOffset, TempI;
	unsigned short * pPacket;
	pMACHdr	= (struct TMACHeader *)pData;
	switch	((*pMACHdr).MACType)
	{
		case cMACTYPE_IP:
			pIPHdr = (struct TIPHeader *)&(pData[cHdrOff_MAC_IP]);
			//	如果目的IP不是本IP则退出。
			if(((*pIPHdr).DestAddr.Addr4_3!= vIP_SelfIP.Addr4_3) && ((*pIPHdr).DestAddr.Addr4_3 !=0xFFFF))	                           return;
			if(((*pIPHdr).DestAddr.Addr2_1!= vIP_SelfIP.Addr2_1) && ((*pIPHdr).DestAddr.Addr2_1 !=0xFFFF))	                           return;

			UDPOffset=(((*pIPHdr).TOS_Version >> 8) & 0x0F) * 2;//计算IP手部长度,一般情况下应该是10(字)。
			TempI =	IP_ChkSum(&(pData[cHdrOff_MAC_IP]), UDPOffset);
			if (TempI != 0xFFFF)
				break;
			pPacket	= &pData[cHdrOff_MAC_IP + UDPOffset];
			TempI =	((*pIPHdr).TotalLength >> 1) - UDPOffset; //Packet Length
			if((*pIPHdr).TotalLength & 1)
				TempI++;
			switch (((*pIPHdr).Protocol_TTL) & 0xFF)
			{	//根据IP包的协议字段,分支,
				case	cIPTYPE_ICMP	:	//	ICMP
					IP_DealWith_ICMP(pData,	pPacket,	TempI);
					break;

				case	cIPTYPE_IGMP	:	//	IGMP
					IP_DealWith_IGMP(pData,	pPacket,	TempI);
					break;

				case	cIPTYPE_UDP	:		//UDP
					IP_DealWith_UDP(pData,	pPacket,	TempI);
					break;

				case	cIPTYPE_TCP	:		//TCP
					IP_DealWith_TCP(pData,	pPacket,	TempI);
					break;
				default	:
					break;
			}
			break;
		case	cMACTYPE_ARP:
			IP_ARPPacketReceived(pData);
			break;
		default	:
			break;
	}
}
//=================================================================================





//=================================================================================
void IP_ARPPacketReceived(unsigned short * pDataPacket)
{
	struct	TARPPacket * pARPPacket;
	struct	TARP	   * pARP;

	pARPPacket = (struct TARPPacket*)pDataPacket;
	pARP = &(*pARPPacket).ARP;


	//	如果目的IP不是本IP则退出。
	if	((*pARP).Receive_IPAddr.Addr4_3	!= vIP_SelfIP.Addr4_3)	return;
	if	((*pARP).Receive_IPAddr.Addr2_1	!= vIP_SelfIP.Addr2_1)	return;

	//	检查是否是一个正确的ARP数据包
	if	((*pARP).Hard_Type != 1) return;
	if	((*pARP).Protocol_type != 0x0800) return;
	if	((*pARP).Protocol_Hard_Length != 0x0604) return;

	if((*pARP).OP_Code == 1)
	{	//这是一个ARP请求,应该响应他,返回自己的MAC地址。
		(*pARPPacket).DestMAC =	(*pARPPacket).SrcMAC;	// 修改MAC的地址
		(*pARPPacket).SrcMAC  =	cMAC_Self;		// 设置自己的MAC地址
		(*pARP).OP_Code	= 2;				// 这是一个ARP应答包
		(*pARP).Receive_MACAddr	= (*pARP).Send_MACAddr;
		(*pARP).Send_MACAddr	= cMAC_Self;		// 设置自己的MAC地址	
		(*pARP).Receive_IPAddr	= (*pARP).Send_IPAddr;	// 设置目的IP;
		(*pARP).Send_IPAddr	= vIP_SelfIP;		// 设置自己的IP。
		//发送数据
		RTL8019_Send((unsigned short*)pDataPacket, sizeof(struct TARPPacket),(unsigned short*)pDataPacket, 0);
	}
	else if	((*pARP).OP_Code == 2)
	{	//这是一个ARP应答,应该把对方的IP和MAC地址保存到自己的缓冲区中。
		vIP_IPMACTable[vIP_IPMACTablePointer].ip  = (*pARP).Send_IPAddr;
		vIP_IPMACTable[vIP_IPMACTablePointer].MAC	=	(*pARP).Send_MACAddr;
		vIP_IPMACTablePointer++;
		if	(vIP_IPMACTablePointer	==	cIP_IPMACTableSize)
			vIP_IPMACTablePointer	=	0;
	}
}
//=================================================================================



//=================================================================================
//struct	TMAC	IP_IP2MAC
void	IP_SendARP(struct	TIPAddr	ip)
{
	struct	TARP*	pARP;
	struct	TARPPacket*	pARPPacket;

	pARPPacket	=	(struct	TARPPacket*)vIP_DataBuf;

	(*pARPPacket).DestMAC	=	cMAC_Board;
	(*pARPPacket).SrcMAC	=	cMAC_Self;
	(*pARPPacket).MACType	=	cMACTYPE_ARP;

	pARP	=	&((*pARPPacket).ARP);
	(*pARP).Hard_Type		=	1;
	(*pARP).Protocol_type	=	0x0800;
	(*pARP).Protocol_Hard_Length	=	0x0604;
	(*pARP).OP_Code			=	1;
	(*pARP).Send_MACAddr	=	cMAC_Self;
	(*pARP).Send_IPAddr		=	vIP_SelfIP;
	(*pARP).Receive_MACAddr	=	cMAC_Board;
	(*pARP).Receive_IPAddr	=	ip;

	RTL8019_Send(vIP_DataBuf,	sizeof(struct	TARPPacket),	vIP_DataBuf, 0);
}
//=================================================================================






//=================================================================================
void	IP_DealWith_ICMP(unsigned short * pHeader, unsigned short * pPacket, unsigned short PacketLength)
{
	struct	TICMPHeader * pICMP;

	if (IP_ChkSum(pPacket,	PacketLength) != 0xFFFF)	return;

	pICMP = (struct	TICMPHeader *)pPacket;
	switch	(((*pICMP).Type_Code >>	8) & 0xFF)
	{
		case	cICMP_PingRequest:	//Ping
			IP_PingResponse(pHeader,	PacketLength);
			break;
		default	:	//没有实现其他的ICMP
			break;
	}
}
//=================================================================================






//=================================================================================
void	IP_DealWith_IGMP(unsigned short * pHeader, unsigned short * pPacket, unsigned short PacketLength)
{
}
//=================================================================================






//=================================================================================
void	IP_DealWith_UDP(unsigned short*	pHeader, unsigned short * pPacket, unsigned short PacketLength)
{
	struct	TMACHeader	*	pMAC;	
	struct	TPre_UDPHeader	*	pPreUDP;
	struct	TUDPHeader	*	pUDP;
	struct	TIPHeader	*	pIP;
	struct	TClientInfo		MyClient;
	short	i;

	pMAC	= (struct TMACHeader *)pHeader;
	pPreUDP	= (struct TPre_UDPHeader *)(pPacket + PacketLength);
	pUDP	= (struct TUDPHeader *)pPacket;

	pIP = (struct TIPHeader	*)&(pHeader[cHdrOff_MAC_IP]);

	//	手动设置PreUDP伪首部,目的是:计算校验和
	(*pPreUDP).DestAddr	=	(*pIP).DestAddr;
	(*pPreUDP).SrcAddr	=	(*pIP).SrcAddr;
	(*pPreUDP).Length	=	(*pUDP).Length;
	(*pPreUDP).Protocol_Value = cIPTYPE_UDP;

	if ((*pUDP).Length & 1)
	{
	  pPacket[PacketLength-1] &= 0xFF00;
	}

	if (IP_ChkSum(pPacket, PacketLength + 6) != 0xFFFF) return;

	MyClient.MAC = (*pMAC).SrcMAC;
	MyClient.IP  = (*pIP).SrcAddr;
	MyClient.Port= (*pUDP).SrcPort;

	if (i =	App_DoCommand((*pUDP).DestPort,	MyClient, pPacket + cHdrOff_UDP_Data, PacketLength - cHdrOff_UDP_Data))
	{
		//有数据需要发送
	  IP_SendUDP(MyClient,i);
	}

/*	if	((*pUDP).DestPort == 30000)
	{
		(*pMAC).DestMAC	= (*pMAC).SrcMAC;
	}*/
}
//=================================================================================






//=================================================================================
void	IP_DealWith_TCP(unsigned short*	pHeader, unsigned short* pPacket, unsigned short PacketLength)
{
}
//=================================================================================






//=================================================================================
unsigned short IP_ChkSum(unsigned short * pData, unsigned short	PacketLength)
{
	unsigned	short	i;
	unsigned	long	TempI;

	TempI =	0;
	for (i=0; i<PacketLength; i++)
	{
	  TempI	+= (pData[i]);
	}
	i = TempI + (TempI >> 16);
	return	i;
}
//=================================================================================




//	这里有一个隐含的数据缓冲区,
//	也就是说,发送的数据,都存在vIP_DataBuf中,其中要发送的数据,在App Layer中设置
//而数据头,则在此设置。
//=================================================================================
void	IP_SendUDP(struct TClientInfo Client, short DataLength)
{
	struct	TUDPPacket	*	pUDP;
	struct	TPre_UDPHeader	*	pPreUDP;

	pUDP = (struct TUDPPacket *)vIP_DataBuf;

	//	MAC
	(*pUDP).MACHdr.DestMAC	= Client.MAC;
	(*pUDP).MACHdr.SrcMAC	= cMAC_Self;
	(*pUDP).MACHdr.MACType	= cMACTYPE_IP;

	//	IP
	(*pUDP).IPHdr.TOS_Version = 0x4500;
	(*pUDP).IPHdr.TotalLength = (cHdrOff_IP_UDP + cHdrOff_UDP_Data + DataLength) *2;
	(*pUDP).IPHdr.ID	  = vIP_IPID;
	vIP_IPID++;
	(*pUDP).IPHdr.Flag_Offset  = 0;
	(*pUDP).IPHdr.Protocol_TTL = cIPTYPE_UDP + 0x8000;
	(*pUDP).IPHdr.DestAddr	   = Client.IP;
	(*pUDP).IPHdr.SrcAddr	   = vIP_SelfIP;
	(*pUDP).IPHdr.ChkSum	   = 0;
	(*pUDP).IPHdr.ChkSum	   = 0xFFFF - IP_ChkSum((unsigned short*)&((*pUDP).IPHdr), cHdrOff_IP_UDP);

	if (IP_ChkSum(vIP_DataBuf + cHdrOff_MAC_IP, cHdrOff_IP_UDP) != 0xFFFF)	return;

	//	UDP
	(*pUDP).UDPHdr.DestPort	= Client.Port;
	(*pUDP).UDPHdr.Length	= (cHdrOff_UDP_Data + DataLength) *2;
	(*pUDP).UDPHdr.SrcPort	= cAppPort_Command;
	//	UDP 伪首部
	pPreUDP	= (struct TPre_UDPHeader *)(vIP_DataBuf + cHdrOff_MAC_IP + cHdrOff_IP_UDP + cHdrOff_UDP_Data + DataLength);
	(*pPreUDP).DestAddr		=	Client.IP;
	(*pPreUDP).Protocol_Value	=	cIPTYPE_UDP;
	(*pPreUDP).SrcAddr		=	vIP_SelfIP;
	(*pPreUDP).Length		=	(*pUDP).UDPHdr.Length;
	//	UDP	校验和
	(*pUDP).UDPHdr.ChkSum	=	0;
	(*pUDP).UDPHdr.ChkSum	= 0xFFFF - IP_ChkSum((unsigned short*)&((*pUDP).UDPHdr), cHdrOff_UDP_Data + DataLength + 6);

	if(IP_ChkSum(vIP_DataBuf + cHdrOff_MAC_IP + cHdrOff_IP_UDP, cHdrOff_UDP_Data + DataLength + 6) ! = 0xFFFF) return;

	//	Send	Data
	RTL8019_Send(vIP_DataBuf, cHdrOff_MAC_IP + cHdrOff_IP_UDP + cHdrOff_UDP_Data + DataLength,vIP_DataBuf, 0);
}
//=================================================================================






//=================================================================================
void	IP_PingResponse(unsigned short * pHeader, short	PacketLength)
{
	struct	TMACHeader	*	pMAC;
	struct	TIPHeader	*	pIP;
	struct	TICMPHeader	*	pICMP;
	short	IPHeaderLen;

	//定位各个报头
	pMAC = (struct TMACHeader *)pHeader;
	pIP  = (struct TIPHeader *)&(pHeader[cHdrOff_MAC_IP]);
	IPHeaderLen = (((*pIP).TOS_Version >> 8) & 0x0F) * 2;	//	计算IP手部长度,一般情况下应该是10(字)。
	pICMP =	(struct	TICMPHeader *)&(pHeader[cHdrOff_MAC_IP + IPHeaderLen]);

	//初始化 MAC
	(*pMAC).DestMAC	= (*pMAC).SrcMAC;
	(*pMAC).SrcMAC	= cMAC_Self;
	//(*pMAC).MACType = 0x0800;//IP包

	//初始化 IP
	(*pIP).Flag_Offset	=	0;
	(*pIP).ChkSum		=	0;
	(*pIP).DestAddr		=	(*pIP).SrcAddr;
	(*pIP).SrcAddr		=	vIP_SelfIP;
	(*pIP).ChkSum		=	0xFFFF - IP_ChkSum((unsigned short*)pIP, IPHeaderLen);
	if (IP_ChkSum((unsigned	short*)pIP, IPHeaderLen) != 0xFFFF) return;

	//初始化	ICMP	-	Ping	Response
	(*pICMP).Type_Code	=	cICMP_PingResponse;
	(*pICMP).ChkSum		=	0;
	(*pICMP).ChkSum		=	0xFFFF - IP_ChkSum((unsigned short*)pICMP, PacketLength);

	if (IP_ChkSum((unsigned short*)pIP, IPHeaderLen) != 0xFFFF) return;
	if (IP_ChkSum((unsigned short*)pICMP, PacketLength) != 0xFFFF) return;

	//发送回应
	RTL8019_Send(pHeader, cHdrOff_MAC_IP + IPHeaderLen + PacketLength, pHeader, 0);
}
//=================================================================================


⌨️ 快捷键说明

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