📄 ip layer.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 + -