📄 ne2000.c
字号:
#if DEBUG == 1
sprintf(tmpstr,"ARP source ip %d.%d.%d.%d\n", (uint)source_ip[0], (uint)source_ip[1]
, (uint)source_ip[2], (uint)source_ip[3]);
trans_str(tmpstr);
sprintf(tmpstr,"ARP dest ip %d.%d.%d.%d\n", (uint)dest_ip[0], (uint)dest_ip[1]
, (uint)dest_ip[2], (uint)dest_ip[3]);
trans_str(tmpstr);
#endif
if (dest_ip[0] == my_ip[0] && dest_ip[1] == my_ip[1] &&
dest_ip[2] == my_ip[2] && dest_ip[3] == my_ip[3]) {
// The ARP was for us, so let's respond
arp_response();
}
break;
case IP:
#if DEBUG == 1
trans_str("IP");
#endif
// Recieve IP Header
version = myinportb(NIC_DATA);
hdr_len = (version & 0x0F) << 2;
opt_len = hdr_len - 20;
version = version >> 4 ;
// if (hdr_len < 0)
// break;
// discard type of service
myinportb(NIC_DATA);
// IP packet length
IP_length = myinportb(NIC_DATA) << 8;
IP_length += myinportb(NIC_DATA);
// Identification
identification = myinportb(NIC_DATA) << 8;
identification += myinportb(NIC_DATA);
// Fragment
fragment = myinportb(NIC_DATA) << 8;
fragment += myinportb(NIC_DATA);
// dicard time to live (the packets already here)
myinportb(NIC_DATA);
// IP Protocol
IP_protocol = myinportb(NIC_DATA);
// get header checksum
chksum = myinportb(NIC_DATA)<<8;
chksum += myinportb(NIC_DATA);
// get ip address of packet source
for (i=0; i<4 ; i++)
source_ip[i] = myinportb(NIC_DATA);
// get ip address of destination
for (i=0; i<4 ; i++)
dest_ip[i] = myinportb(NIC_DATA);
trans_str("\n");
for (i=0; i<4 ; i++)
{
sprintf(tmpstr,"%d.",(uint)source_ip[i]);
trans_str(tmpstr);
}
trans_str("\n->");
for (i=0; i<4 ; i++)
{
sprintf(tmpstr,"%d.",(uint)dest_ip[i]);
trans_str(tmpstr);
}
trans_str("\n");
// discard options if any
for (i=0; i<opt_len ; i++)
myinportb(NIC_DATA);
#if DEBUG == 1
sprintf(tmpstr,"Option length = %d\n",(uint)opt_len);
trans_str(tmpstr);
#endif
switch (IP_protocol) {
case ICMP:
#if DEBUG == 1
trans_str("-ICMP");
#endif
icmp_type = myinportb(NIC_DATA);
if (icmp_type == ECHO) {
#if DEBUG == 1
trans_str("--PING");
#endif
// This is a PING
// retrieve 'code'
icmp_code = myinportb(NIC_DATA);
// retrieve 'checksum'
icmp_checksum = myinportb(NIC_DATA)<<8;
icmp_checksum += myinportb(NIC_DATA);
// retrieve 'identifier'
icmp_identifier = myinportb(NIC_DATA)<<8;
icmp_identifier += myinportb(NIC_DATA);
// retrieve 'sequence'
icmp_sequence = myinportb(NIC_DATA)<<8;
icmp_sequence += myinportb(NIC_DATA);
ping_response();
}
// Add other ICMP types here
break;
case TCP:
#if DEBUG == 1
trans_str("-TCP");
#endif
// retrieve 'source port'
tcp_source_port = myinportb(NIC_DATA)<<8;
tcp_source_port += myinportb(NIC_DATA);
// retrieve 'destination port'
tcp_dest_port = myinportb(NIC_DATA)<<8;
tcp_dest_port += myinportb(NIC_DATA);
// We only respond to port 80 (HTML requests)
if (tcp_dest_port != 80) break;
// retrieve sequence number
seq[0]=myinportb(NIC_DATA)<<8;
seq[0]+=myinportb(NIC_DATA);
seq[1]=myinportb(NIC_DATA)<<8;
seq[1]+=myinportb(NIC_DATA);
// retrieve acknowlegment number
ack[0]=myinportb(NIC_DATA)<<8;
ack[0]+=myinportb(NIC_DATA);
ack[1]=myinportb(NIC_DATA)<<8;
ack[1]+=myinportb(NIC_DATA);
// retrieve offset
offset=(myinportb(NIC_DATA) & 0xF0) >> 2;
tcp_options = (offset - 20);
// retrieve flags
flags=myinportb(NIC_DATA) & 0x3F;
if ((flags & TCP_SYN) == TCP_SYN) max_seg=0;
// retrieve windows
window0=myinportb(NIC_DATA) << 8;
window0+=myinportb(NIC_DATA);
// discard checksum
myinportb(NIC_DATA);
myinportb(NIC_DATA);
// discard urgent pointer
myinportb(NIC_DATA);
myinportb(NIC_DATA);
// Handle options
for (i=0 ; i < tcp_options ; i++) {
kind = myinportb(NIC_DATA);
switch (kind) {
case 2:
myinportb(NIC_DATA);
if ((flags & TCP_SYN) == TCP_SYN) {
max_seg = myinportb(NIC_DATA) << 8;
max_seg += myinportb(NIC_DATA);
} else {
myinportb(NIC_DATA);
myinportb(NIC_DATA);
}
i=i+3;
case 0:
case 1:
break;
}
}
tcp_response();
break;
case UDP:
#if DEBUG == 1
trans_str("-UDP");
#endif
break;
}
}
myoutportb(CR, 0x22);
myoutportb(BNDRY, next_ptr);
return FALSE;
}
return TRUE;
}
// ********************************************************
void arp_response(void) {
u16_t i;
// prepare ethernet packet
load_ethernet_header();
// packet type
myoutportb(NIC_DATA, ARP >> 8);
myoutportb(NIC_DATA, ARP );
// hardware type (0x0001 = ethernet)
myoutportb(NIC_DATA, 0x00);
myoutportb(NIC_DATA, 0x01);
// protocol type (0x0800 = IP)
myoutportb(NIC_DATA, 0x08);
myoutportb(NIC_DATA, 0x00);
// hardware address length (6 bytes)
myoutportb(NIC_DATA, 0x06);
// protocol address length (4 bytes)
myoutportb(NIC_DATA, 0x04);
// opcode (ARP reply)
myoutportb(NIC_DATA, 0x00);
myoutportb(NIC_DATA, 0x02);
// my hardware address
for (i=0 ; i<6 ; i++)
myoutportb(NIC_DATA, physical_address[i]);
// my ip address
for (i=0 ; i<4 ; i++)
myoutportb(NIC_DATA, my_ip[i]);
// source hardware address
for (i=0 ; i<6 ; i++)
myoutportb(NIC_DATA, source_address[i]);
// source ip address
for (i=0 ; i<4 ; i++)
myoutportb(NIC_DATA, source_ip[i]);
// pad to 46 bytes (46-28=18)
for (i=0 ; i<18 ;i++)
myoutportb(NIC_DATA, 0x00);
// packet assmebled so let's send it
send_packet(60);
}
// ********************************************************
void load_ethernet_header(void) {
u16_t i;
remote_dma_setup(WRITE, XMT_BUF_START << 8);
// write hardware addresses
for(i=0 ; i<6 ; i++)
myoutportb(NIC_DATA, source_address[i]);
for(i=0 ; i<6 ; i++)
myoutportb(NIC_DATA, physical_address[i]);
}
// ********************************************************
void send_packet(u16_t len) {
myoutportb(CR, 0x22);
myoutportb(TBCR0, len );
myoutportb(TBCR1, len >> 8);
myoutportb(TPSR, XMT_BUF_START);
myoutportb(CR, 0x26);
}
// ********************************************************
void ping_response() {
u16_t prev_chksum;
u16_t i;
// prepare ethernet packet
load_ethernet_header(); // Load MAC source and destination addresses
// prepare IP header
load_IP_header(28,ICMP); // load IP header
chksum=0;
myoutportw(NIC_DATA, (u16_t)icmp_code); // Type = 0 (echo reply)
prev_chksum=chksum;
chksum += icmp_identifier;
if (chksum<prev_chksum) chksum++;
prev_chksum=chksum;
chksum += icmp_sequence;
if (chksum<prev_chksum) chksum++;
myoutportw(NIC_DATA, ~chksum);
myoutportw(NIC_DATA, icmp_identifier);
myoutportw(NIC_DATA, icmp_sequence);
for (i=0 ; i<18 ; i++)
myoutportb(NIC_DATA, 0x00); // pad to 60 bytes + 4 for CRC = 64 (min ethernet packet)
send_packet(60);
}
// ********************************************************
void load_IP_header(u16_t IP_packet_length, u16_t IP_send_protocol) {
u16_t i;
u16_t prev_chksum;
myoutportb(NIC_DATA, IP >> 8); // IP packet
myoutportb(NIC_DATA, IP);
chksum = 0;
myoutportw(NIC_DATA, 0x4500);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -