📄 ip_udp.c
字号:
/**************************************************************************
**
** 文件: IP_UDP.c
** 描述: 该文件完成该文件完成与IP/UDP协议相关的报文的收发
**
**************************************************************************/
//include library files
#include <stdio.h>
#include <string.h>
#include <iom128v.h>
//include user defined files
#include "Define.h"
#include "Global_Variable.h"
#include "Extern_Function.h"
#include "IP_UDP.h"
static uchar Req_MAC[6]={0x00,0x00,0x00,0x00,0x00,0x00}; //ARP请求的MAC地址
static uchar *Req_IP; //ARP请求的IP地址
static uint IP_Seq=0; //IP标识,即发送第几个IP报文
static uint ICMP_Seq=0; //Ping序号,即第几个Ping包
uchar ARP_Ed=FALSE; //是否接收到ARP应答的标志
uchar Ping_Ed=FALSE; //是否接收到Ping应答的标志
/**************************************************************************
**
** 函数: void Make_Ether_Header(uchar *,uchar *,uint)
** 描述: 该函数完成以太网头的构造,入口参数分别为目标MAC、源MAC、帧类型
**
**************************************************************************/
void Make_Ether_Header(uchar *dhost,uchar *shost,uint type)
{
memcpy(S_Ehe->Ether_Dest_MAC,dhost,6);
memcpy(S_Ehe->Ether_Sour_MAC,shost,6);
S_Ehe->Ether_Type=htons(type);//变字节序,将一个16位数从主机字节顺序转换成网络字节顺序
}
/**************************************************************************
**
** 函数: uint Check_Sum(uint *,uint)
** 描述: 该函数用于计算校验和,入口参数为待校验的数据首地址和数据长度,返回校验值
**
**************************************************************************/
uint Check_Sum(uint *data,uint nbytes)
{
uint index;
ulong sum=0;
for(;nbytes>1;nbytes-=2)
{
sum+=*(data++);
if(sum&0x80000000)
sum=(sum&0xffff)+(sum>>16);
}
if(nbytes==1)
{
index=0;
*(uchar *)(&index)=*(uchar *)data;
sum+=index;
}
while(sum>>16)
sum=(sum&0xffff)+(sum>>16);
return (sum==0xffff)?sum:~sum;
}
/**************************************************************************
**
** 函数: void Send_ARP_REQ(uchar *)
** 描述: 该函数完成ARP请求报文的发送,入口参数为ARP请求的IP地址
**
**************************************************************************/
void Send_ARP_REQ(uchar *ip)
{
ulong *remip,*locip,*msk;
remip=(ulong *)ip;
locip=(ulong *)My_IP;
msk=(ulong *)Mask;
Req_IP=(((*remip^*locip)&*msk)==0)?ip:Gate; //判断是否属于同一个子网
Make_Ether_Header(Bro_MAC,My_MAC,Ether_Type_ARP);
S_Arp->ARP_Net_Type=htons(1); //以太网为0x0001
S_Arp->ARP_Protocol=htons(Ether_Type_IP); //要转换的协议类型,IP协议为0x0800
S_Arp->ARP_MAC_Len=6; //MAC地址字节长度为0x06
S_Arp->ARP_IP_Len=4; //IP地址字节长度为0x04
S_Arp->ARP_Operator=htons(ARP_REQ); //操作类型ARP_REQ=0x0001,ARP_ACK=0x0002
memcpy(S_Arp->ARP_Sour_MAC,My_MAC,6); //发送方MAC地址
memcpy(S_Arp->ARP_Sour_IP,My_IP,4); //发送方IP地址
memcpy(S_Arp->ARP_Dest_MAC,Req_MAC,6); //接收方MAC地址
memcpy(S_Arp->ARP_Dest_IP,Req_IP,4); //接收方IP地址
//ARP请求报文打包结束,作为优先级为1的非周期报文传给EPA_CSME
EPA_CSME(sizeof(struct Ether_Header)+sizeof(struct ARP));
}
/**************************************************************************
**
** 函数: void Send_ARP_ACK(uint)
** 描述: 该函数完成ARP应答报文的发送,入口参数为接收到的包的长度
**
**************************************************************************/
void Send_ARP_ACK(uint packetlen)
{
memcpy(Send_Buf,Rece_Buf,packetlen); //利用ICMP请求构造ICMP应答
memcpy(S_Ehe->Ether_Dest_MAC,S_Ehe->Ether_Sour_MAC,6);
memcpy(S_Ehe->Ether_Sour_MAC,My_MAC,6);
S_Arp->ARP_Operator=htons(ARP_ACK); //操作类型ARP_REQ=0x0001,ARP_ACK=0x0002
memcpy(S_Arp->ARP_Dest_MAC,S_Arp->ARP_Sour_MAC,6);//接收方MAC地址
memcpy(S_Arp->ARP_Dest_IP,S_Arp->ARP_Sour_IP,4); //接收方IP地址
memcpy(S_Arp->ARP_Sour_MAC,My_MAC,6); //发送方MAC地址
memcpy(S_Arp->ARP_Sour_IP,My_IP,4); //发送方IP地址
EPA_CSME(packetlen); //ARP应答报文打包结束,作为优先级为1的非周期报文传给EPA_CSME
}
/**************************************************************************
**
** 函数: void Receive_ARP(uint)
** 描述: 该函数完成ARP报文的接收,入口参数为接收到的包的长度
**
**************************************************************************/
void Receive_ARP(uint len)
{
if(memcmp(R_Arp->ARP_Dest_IP,My_IP,4)==0) //ARP报文是在呼叫自己
{
if((ntohs(R_Arp->ARP_Net_Type)==1)&&(ntohs(R_Arp->ARP_Protocol)==Ether_Type_IP)) //以太网且为IP协议
{
if(ntohs(R_Arp->ARP_Operator)==ARP_REQ) //处理ARP请求
Send_ARP_ACK(len);
else if(ntohs(R_Arp->ARP_Operator)==ARP_ACK) //处理ARP应答
{
if(memcmp(R_Arp->ARP_Sour_IP,Req_IP,4)==0)//发送方IP与一开始本地发送的IP请求地址一致
{
memcpy(Dest_MAC,R_Arp->ARP_Sour_MAC,6); //将获得的MAC地址拷贝
ARP_Ed=TRUE;
}
}
}
}
}
/**************************************************************************
**
** 函数: void Send_IP(uchar *,uchar *,uint,uchar,uchar,uchar)
** 描述: 该函数完成IP报文的发送,入口参数为目的MAC、目的IP、数据长度、上层协议、服务类型、生存时间
**
**************************************************************************/
void Send_IP(uchar *dmac,uchar *dip,uint datalen,uchar pro,uchar tos,uchar ttl)
{
uint type=0,packetlen=0;
if(memcmp(dmac,Bro_MAC,6)!=0 && ARP_Ed==FALSE) //还未收到正确的ARP响应
{
Send_ARP_REQ(dip);
while(ARP_Ed==FALSE)
{
if((packetlen=Receive_Packet(Rece_Buf))>0)
{
Set_R_Pointer();
type=ntohs(R_Ehe->Ether_Type);
if(type==Ether_Type_ARP)
Receive_ARP(packetlen);
else if(type==Ether_Type_IP)
Receive_IP(packetlen);
}
}
}
Make_Ether_Header(dmac,My_MAC,Ether_Type_IP);
IP_Seq++; //IP标识加1
S_Pip->IP_VerLen=(IP_Version<<4)|(IP_Header_MinLen>>2);//IP版本以及头长度
S_Pip->IP_Tos=tos; //服务类型
S_Pip->IP_Len=htons(IP_Header_MinLen+datalen); //除去以太网头的包的总长度
S_Pip->IP_ID=htons(IP_Seq); //IP标识
S_Pip->IP_FlagOffset=htons(0); //标志及片偏移
S_Pip->IP_TTL=ttl; //IP数据报的生存时间,通常用可经过的最大路由器数来表征
S_Pip->IP_Protocol=pro; //上层协议标识,1为ICMP,6为TCP,17为UDP
S_Pip->IP_Check=0; //头部校验和
memcpy(S_Pip->IP_Sour_IP,My_IP,4); //IP源地址
memcpy(S_Pip->IP_Dest_IP,dip,4); //IP目标地址
S_Pip->IP_Check=Check_Sum((uint *)S_Pip,IP_Header_MinLen);
EPA_CSME(IP_Header_MinLen+datalen+sizeof(struct Ether_Header)); //UDP/IP封装结束,传给EPA_CSME
}
/**************************************************************************
**
** 函数: void Receive_IP(uint)
** 描述: 该函数完成IP报文的接收,入口参数为接收到的包的总长度
**
**************************************************************************/
void Receive_IP(uint len)
{
if(((R_Pip->IP_VerLen>>4)==IP_Version)&&((memcmp(R_Pip->IP_Dest_IP,My_IP,4)==0)\
||(memcmp(R_Pip->IP_Dest_IP,Bro_IP,4)==0))) //接收到正确的IP报文
{
if(ARP_Ed==FALSE)
{
memcpy(Dest_MAC,R_Ehe->Ether_Sour_MAC,6);
ARP_Ed=TRUE;
}
if(Check_Sum((uint *)R_Pip,IP_Header_Len)==0xffff)//校验值正确
{
switch(R_Pip->IP_Protocol)
{
case IP_ICMP:Receive_ICMP(len);break;
//case IP_TCP:Receive_TCP();break;
case IP_UDP:Receive_UDP();break;
default:break;
}
}
}
}
/**************************************************************************
**
** 函数: void Send_ICMP_REQ(uchar *)
** 描述: 该函数完成ICMP请求报文的发送,入口参数为ICMP请求的IP地址
**
**************************************************************************/
void Send_ICMP_REQ(uchar *ip)
{
uint i;
ICMP_Seq++; //ICMP标识加1
S_Pic->ICMP_Type=ICMP_Type_REQ;
S_Pic->ICMP_Code=0;
S_Pic->ICMP_Check=0;
S_Pic->ICMP_ID=htons(0); //多个Ping请求时,用于识别与所发送的报文相对应的应答
S_Pic->ICMP_Sequence=htons(ICMP_Seq);//记录发送端的ICMP报文序号
for(i=0;i<ICMP_Num;i++)
S_Pic->ICMP_Data[i]=(uchar)(i%23+'a'); //测试数据
S_Pic->ICMP_Check=Check_Sum((uint *)S_Pic,sizeof(struct ICMP));
Send_IP(Dest_MAC,ip,sizeof(struct ICMP),IP_ICMP,IP_Tos_Value,IP_TTL_Value);
}
/**************************************************************************
**
** 函数: void Send_ICMP_ACK(uint)
** 描述: 该函数完成ICMP应答报文的发送,入口参数为接收到的ICMP请求的包长度
**
**************************************************************************/
void Send_ICMP_ACK(uint packetlen)
{
memcpy(Send_Buf,Rece_Buf,packetlen); //利用ICMP请求构造ICMP应答
memcpy(S_Ehe->Ether_Dest_MAC,S_Ehe->Ether_Sour_MAC,6);
memcpy(S_Ehe->Ether_Sour_MAC,My_MAC,6);
memcpy(S_Pip->IP_Dest_IP,S_Pip->IP_Sour_IP,4);
memcpy(S_Pip->IP_Sour_IP,My_IP,4);
S_Pip->IP_Check=0;
S_Pip->IP_Check=Check_Sum((uint *)S_Pip,IP_Header_Len);
S_Pic->ICMP_Type=ICMP_Type_ACK;
S_Pic->ICMP_Check=0;
S_Pic->ICMP_Check=Check_Sum((uint *)S_Pic,packetlen-sizeof(struct Ether_Header)-IP_Header_Len);
EPA_CSME(packetlen); //Ping应答报文打包结束,作为优先级为4的非周期报文传给EPA_CSME
}
/**************************************************************************
**
** 函数: void Receive_ICMP(uint)
** 描述: 该函数完成ICMP报文的接收,入口参数为接收到的ICMP包长度
**
**************************************************************************/
void Receive_ICMP(uint packetlen)
{
if(Check_Sum((uint *)R_Pic,packetlen-sizeof(struct Ether_Header)-IP_Header_Len)==0xffff)//收到正确的ICMP报文
{
switch(R_Pic->ICMP_Type)
{
case ICMP_Type_REQ:Send_ICMP_ACK(packetlen);break; //收到Ping请求,发Ping应答
case ICMP_Type_ACK:Ping_Ed=TRUE;break; //收到Ping应答,置标志位
default:break;
}
}
}
/**************************************************************************
**
** 函数: void Send_UDP(uchar *,uchar *,uint,uint,uint)
** 描述: 该函数完成UDP报文的发送,入口参数为目标MAC、目标IP、源端口、目的端口、数据长度
**
**************************************************************************/
void Send_UDP(uchar *fmac,uchar *fip,uint sport,uint dport,uint datalen)
{
S_Pdp->UDP_Sour_Port=htons(sport);
S_Pdp->UDP_Dest_Port=htons(dport);
S_Pdp->UDP_Len=htons(UDP_Header_Len+datalen);
S_Pdp->UDP_Check=0;
S_Pdp->UDP_Check=Check_Sum((uint *)S_Pdp,UDP_Header_Len+datalen);
Send_IP(fmac,fip,UDP_Header_Len+datalen,IP_UDP,IP_Tos_Value,IP_TTL_Value);
}
/**************************************************************************
**
** 函数: void Receive_UDP(void)
** 描述: 该函数完成UDP报文的接收
**
**************************************************************************/
void Receive_UDP(void)
{
if(Check_Sum((uint *)R_Pdp,ntohs(R_Pdp->UDP_Len))==0xffff) //收到正确的UDP报文
Socket_Depacket(); //传给EPA套接字映射接口
}
/******************* End Of File **********************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -