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

📄 ip.c

📁 51单片机加rt8019硬件平台,上web方案及详细代码
💻 C
字号:
//---------------------------------ip.c--------------------------
//#define DEBUG        
  
#include<string.h>	
#include"includes.h"

/*****************************************
IP包发送
outbuf  发送缓冲区首地址
ipaddr  目的IP地址
len     IP数据包长度不包括首部
*****************************************/
void ip_send(uchar xdata * outbuf, ulong ipaddr, uchar proto_id, uint len)
{
   Ip_Header xdata * ip;
   uchar * macaddr = NULL;
   static uint ip_ident = 0;   
   /* 填充IP首部*/ 
   ip = (Ip_Header xdata *)(outbuf + 14);//保留14个字节以太网首部
   ip->ver_len = 0x45;                   // IPv4 5 x 4= 20 byte首部长度
   ip->tos = 0;		                    //一般服务
   ip->total_len = 20 + len;
   ip->id = ip_ident++;     	           //标识
   ip->fragment_info = 0;                //不分片
   ip->ttl = 32;           	
   ip->protocol_id = proto_id;  
   ip->hd_cksum = 0;
   ip->source_ipaddr = myipaddr;    
   ip->dest_ipaddr = ipaddr;
   ip->hd_cksum = ~cksum(outbuf + 14, 20);//只计算首部校验和 

   /*根据IP查找MAC*/  
   macaddr = arp_search(ip->dest_ipaddr);
//   TRACE("ip_send > macaddr=",macaddr,6,0);
  
	if (macaddr == NULL) //没找到MAC地址则备份当前要发送的内容,在收到ARP应答后发送
	{       
	   wait.buf = bakbuf;
      memcpy(wait.buf, outbuf, 34 + len);
             
		wait.ipaddr = ip->dest_ipaddr;
		wait.proto_id = proto_id;
		wait.len = len;
		wait.timer = ARP_TIMEOUT;
		TRACE("BACKUP IP=",CP &ip->dest_ipaddr,4,0);
       
      /*没找到MAC则发送ARP请求*/
      arp_send(outbuf,NULL, ip->dest_ipaddr, ARP_REQUEST); 
	   waiting_for_arp = TRUE;	  //置ARP等待标志
	   SetTimer(ARP_RESEND,50); //100ms
      return;
	}	
	
	eth_send(outbuf, macaddr, IP_PACKET, 20 + len);	
}
/*****************************************
IP包接收
计算首部长度和数据长度
计算首不校验和
*****************************************/
void ip_receive(uchar xdata * inbuf)
{
	Ip_Header xdata * ip;
	uint idata header_len, payload_len;
		
	ip = (Ip_Header xdata *)(inbuf + 14);            
  
	if (ip->dest_ipaddr != myipaddr) 
	{
		TRACE("ip->dest_ipaddr",CP &ip->dest_ipaddr,4,0);
		TRACE("myipaddr = ",CP &myipaddr,4,0);
		return;    
	}

	header_len = 4 * (0x0F & ip->ver_len);     //首部长度
	payload_len = ip->total_len - header_len;  //数据长度

	if (cksum(inbuf + 14, header_len) != 0xFFFF)	
	{
		TRACE("cksum header != 0xffff",NULL,0,0);
		return;    
	}
	
	if ((ip->ver_len >> 4) != 0x04)	 //版本
	{
		TRACE("ip->ver_len != 0x04",NULL,0,0);
		return;    
	}
		
	if ((ip->fragment_info & 0x3FFF) != 0)  //不分片
	{
		TRACE("ip->fragment_info",NULL,0,0);
		return;    
	}

	if (header_len > 20)
	{      
		memmove(inbuf + 34, inbuf + 14 + header_len, payload_len); //去掉选项数据
		
		header_len = 20;   //调整首部信息
		ip->ver_len = 0x45;
		ip->total_len = 20 + payload_len;
	}	

	switch (ip->protocol_id)
	{
		case ICMP_TYPE:
			TRACE("R: ICMP_TYPE",NULL,0,0);
			icmp_receive(inbuf, payload_len);
			break;

		case IGMP_TYPE:
			TRACE("R: IGMP_TYPE",NULL,0,0);
			break;
		  
		case UDP_TYPE:
			TRACE("R: UDP_TYPE",NULL,0,0);
        	udp_receive(inbuf, payload_len);
			break;

		case TCP_TYPE:
			TRACE("R: TCP_TYPE",NULL,0,0); 			 
			tcp_receive(inbuf, payload_len); 
			break; 
		default: 
			TRACE("R: OTHER_TYPE",NULL,0,0); 			 
			break;
   }
}

⌨️ 快捷键说明

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