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