📄 ip.c
字号:
#include "MyLib.h"
//用到gMyIP[4],gIP_ident
extern struct _CONN conn[MAX_CONN+1];//tcpdata.c
U32 Calc_checksum(U8 *buf, U32 len) // 计算16位校验和
{
U32 i,sum=0;
for(i=0; i<len; i++){
if(i&0x01) // 低位
sum+=buf[i];
else // 高位
sum+=(buf[i]*256);
}
while(sum>0xFFFF)
sum=sum/0x10000+sum%0x10000;
sum=0xFFFF-sum;
return sum;
}
//ipaddr=目标地址,proro_id=协议类型
void IP_send(U8 *buf, U8 *ipaddr, U8 proto_id, U32 len)//len是上一级的长度
{
U8 *hwaddr;
U32 sum;
buf[0x0E]=0x45; // IPv4 with 20 byte header
buf[0x0F]=0; // Type_of_service
buf[0x10]=(len+20)/256; buf[0x11]=(len+20)%256; // Total_length
buf[0x12]=gIP_ident/256; buf[0x13]=gIP_ident%256; gIP_ident++;
buf[0x14]=buf[0x15]=0; // Fragment_info=0(not fragmented)
buf[0x16]=0x80; // Time to live
buf[0x17]=proto_id; // Protocol id
buf[0x18]=buf[0x19]=0; // Header checksum
MyMemcpy(buf+0x1A, gMyIP, 4); // Source IP
MyMemcpy(buf+0x1E, ipaddr, 4); // Dest IP
sum=Calc_checksum(buf+14, 20);
buf[0x18]=sum/256; buf[0x19]=sum%256;
hwaddr=Arp_resolve(ipaddr);//查找目标网卡物理地址
if(hwaddr==NULL) // 无效IP地址
return;
MyMemcpy(buf, hwaddr, 6); // 目的网卡MAC地址
MyMemcpy(buf+6, gMyPhy, 6); // 发送网卡MAC地址
buf[0x0C]=0x08; buf[0x0D]=0x00; // IP_Packet
DM9000_SendBuf(buf, len+34);
}
void IP_receive(U8 *buf, U32 len)
{
U16 dat;
U16 header_len, payload_len;
if(MyMemcmp(buf+0x1E, gMyIP, 4)) // 判断是否为本机IP
return;
header_len=(buf[0x0E]&0x0F)*4; // header_len=20
payload_len=buf[0x10]*256+buf[0x11]-header_len;
if(Calc_checksum(buf+14, header_len))// 检查IP校验和
return;
if((buf[0x0E]&0xF0)!=0x40) // 检查IP版本号(IPV4)
return;
dat=buf[0x14]+buf[0x15]*0x100;
if((dat&0xFF3F)!=0) // 检查分段(本系统不支持分段)
return;
if(header_len>20){
MyMemcpy(buf+34, buf+14+header_len, payload_len);
header_len=20; buf[0x0E]=0x45;
buf[0x10]=(payload_len+20)/256; buf[0x11]=(payload_len+20)%256;
}
Arp_update(buf+0x1A, buf+0x06); // 确保IP对应的网卡物理地址在Cache中
switch(buf[0x17]){ // IP协议处理
case ICMP_TYPE: // ICMP协议(Ping)
ICMP_receive(buf, payload_len);//payload是该包的长度,从buf+34开始
break;
case UDP_TYPE: // UDP协议
UDP_receive(buf, payload_len); // UDP数据从第34字节开始,包括8个字节UDP包头
break;
case TCP_TYPE: // TCP协议
//TCP_receive(buf, payload_len); // 真正数据从第34字节开始(14字节以太网头+20字节IP头)
break;
}
}
/*void http_send(U8 *buf, U32 len, U32 nr)
{
U32 tmp,sum;
buf[34]=HTTP_PORT/256; buf[35]=HTTP_PORT%256; // TCP->source_port
MyMemcpy(buf+36, conn[nr].port, 4); // TCP->dest_port
MyMemcpy(buf+38, conn[nr].my_sequence, 4); // TCP->sequence
MyMemcpy(buf+42, conn[nr].his_sequence, 4); // TCP->ack_number
tmp=0x5000 | TCP_ACK;
buf[46]=tmp/256; buf[47]=tmp%256; // TCP->flags
buf[48]=1460/256; buf[49]=1460%256; // tcp->window
buf[50]=buf[51]=0; // tcp->checksum
buf[52]=buf[53]=0; // tcp->urgent_ptr
MyMemcpy(buf+30, conn[nr].ipaddr, 4); // ip->dest_ipaddr
MyMemcpy(buf+26, gMyIP, 4); // ip->source_ipaddr
sum=0xFFFF-Calc_checksum(buf+26, 8+len);
sum+=(len+6);
sum=(sum&0xFFFF)+(sum>>16);
sum=0xFFFF-sum;
buf[50]=sum/256; buf[51]=sum%256; // tcp->checksum
IP_send(buf, conn[nr].ipaddr, TCP_TYPE, len);
}
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -