📄 ne2000.c
字号:
myoutportw(NIC_DATA, IP_packet_length);
myoutportw(NIC_DATA, identification);
myoutportw(NIC_DATA, 0x0000); // Okay to fragment
myoutportw(NIC_DATA, 0xFF00 + IP_send_protocol);
// Time-To-Live set to max 255
prev_chksum = chksum;
chksum += ((u16_t)my_ip[0]<<8) + my_ip[1];
if (chksum < prev_chksum) chksum++;
prev_chksum = chksum;
chksum += ((u16_t)my_ip[2]<<8) + my_ip[3];
if (chksum < prev_chksum) chksum++;
prev_chksum = chksum;
chksum += ((u16_t)source_ip[0]<<8) + source_ip[1];
if (chksum < prev_chksum) chksum++;
prev_chksum = chksum;
chksum += ((u16_t)source_ip[2]<<8) + source_ip[3];
if (chksum < prev_chksum) chksum++;
#if DEBUG > 1
trans_str("-----");
trans_str("4500");
sprintf(tmpstr,"%X\n",(uint)IP_packet_length);
trans_str(tmpstr);
sprintf(tmpstr,"%X\n",(uint)identification);
trans_str(tmpstr);
trans_str("0000");
sprintf(tmpstr,"%X\n",(uint)(0xFF00+IP_send_protocol));
trans_str(tmpstr);
sprintf(tmpstr,"%X\n",(uint)(~chksum));
trans_str(tmpstr);
sprintf(tmpstr,"%X%X\n",(uint)my_ip[0],(uint)my_ip[1]);
trans_str(tmpstr);
sprintf(tmpstr,"%X%X\n",(uint)my_ip[2],(uint)my_ip[3]);
trans_str(tmpstr);
sprintf(tmpstr,"%X%X\n",(uint)source_ip[0],(uint)source_ip[1]);
trans_str(tmpstr);
sprintf(tmpstr,"%X%X\n",(uint)source_ip[2],(uint)source_ip[3]);
trans_str(tmpstr);
#endif
myoutportw(NIC_DATA, ~chksum); // Header Checksum
for (i=0 ; i<4 ; i++) // source IP address for this packet
myoutportb(NIC_DATA, my_ip[i]);
for (i=0 ; i<4 ; i++) // destination IP address for this packet
myoutportb(NIC_DATA, source_ip[i]);
}
// ********************************************************
void tcp_response(void) {
u16_t i;
switch (html_socket) {
case LISTEN:
trans_str("L");
// *** We are expecting a SYN without an ACK
// *** Could get a RST, FIN, PSH or URG but we'll ignore the PSH or URG
if (flags & TCP_SYN) {
// SYN set
// We should check to be sure an ACK wasn't also sent
if (flags & TCP_ACK) {
break; // Ignore it for now. We'll add code to handle later
}
// We shouldn't have a RST or FIN with a SYN
if (flags & TCP_RST || flags & TCP_FIN) {
break; // Ignore it for now. We'll add code to hanlde later
}
// Everything looks okay so handle the SYN request
// Save the senders sequence number
tcp_listen();
}
break;
case SYN_RCVD:
trans_str("S");
// Check if addressed for this socket
if (port!=tcp_source_port || ip[0]!=source_ip[0] || ip[1]!=source_ip[1] ||
ip[2]!=source_ip[2] || ip[3]!= source_ip[3])
break;
// We are expecting an ACK without a SYN
if (flags & TCP_ACK) {
// ACK set
// We should check to be sure an SYN wasn't also sent
if (flags & TCP_SYN) {
break; // Ignore it for now. We'll add code to handle later
}
// We shouldn't have a RST or FIN with an ACK
if (flags & TCP_RST || flags & TCP_FIN) {
break; // Ignore it for now. We'll add code to hanlde later
}
// Everything looks okay so handle the ACK response
tcp_syn_rcvd();
}
break;
case ESTAB:
trans_str("E");
// We are expecting an ACK without or SYN
// We could receive a FIN
if (flags & TCP_ACK) {
// ACK set
// We should check to be sure an SYN wasn't also sent
if (flags & TCP_SYN) {
break; // Ignore it for now. We'll add code to handle later
}
// We shouldn't have a RST with an ACK
if (flags & TCP_RST ) {
break; // Ignore it for now. We'll add code to hanlde later
}
// ************************************************************
// *** - check received sequence number to be sure it's ***
// *** what we expected ***
// *** - check acknowledgement number to be sure it's what ***
// *** we are going to send ***
// *** - check source ip address and source port to be sure ***
// *** they are correct ***
// ************************************************************
if (seq[0] != xm_ack[0] || seq[1] != xm_ack[1] ||
ack[0] != xm_seq[0] || ack[1] != xm_seq[1])
break;
if (port != tcp_source_port)
break;
if (ip[0] != source_ip[0] || ip[1] != source_ip[1] ||
ip[2] != source_ip[2] || ip[3] != source_ip[3])
break;
trans_str("I-");
// Everything looks okay so handle the ACK response
tcp_estab();
}
}
}
// ********************************************************
void load_TCP_header(u16_t data_flags, u16_t tcp_chksum, u16_t tcp_length) {
u16_t prev_chksum;
chksum = tcp_chksum;
// calculate checksum of pseudo header
prev_chksum = chksum;
chksum += ((u16_t)my_ip[0]<<8) + my_ip[1];
if (chksum < prev_chksum) chksum++;
prev_chksum = chksum;
chksum += ((u16_t)my_ip[2]<<8) + my_ip[3];
if (chksum < prev_chksum) chksum++;
prev_chksum = chksum;
chksum += ((u16_t)source_ip[0]<<8) + source_ip[1];
if (chksum < prev_chksum) chksum++;
prev_chksum = chksum;
chksum += ((u16_t)source_ip[2]<<8) + source_ip[3];
if (chksum < prev_chksum) chksum++;
prev_chksum = chksum;
chksum += TCP;
if (chksum < prev_chksum) chksum++;
prev_chksum = chksum;
chksum += tcp_length;
if (chksum < prev_chksum) chksum++;
// source port
myoutportw(NIC_DATA, tcp_dest_port);
// destination port
myoutportw(NIC_DATA, tcp_source_port);
// sequence number
myoutportw(NIC_DATA, xm_seq[0]);
myoutportw(NIC_DATA, xm_seq[1]);
// acknowledment number
myoutportw(NIC_DATA, xm_ack[0]);
myoutportw(NIC_DATA, xm_ack[1]);
// data offset and flags
myoutportw(NIC_DATA, data_flags);
// window0
myoutportw(NIC_DATA, 1460);
// checksum
myoutportw(NIC_DATA, ~chksum);
// urgent pointer
myoutportw(NIC_DATA, 0);
}
// ********************************************************
void tcp_listen(void) {
u16_t i;
xm_ack[0] = seq[0];
xm_ack[1] = seq[1];
port = tcp_source_port;
// Save the source IP address
for (i=0 ; i<4 ; i++)
ip[i] = source_ip[i];
// Calculate data length
tcp_data_len = IP_length - (hdr_len + offset);
// Increment sequence to account for SYN and add data
xm_ack[1] += tcp_data_len + 1;
if (xm_ack[1] < seq[1] )
xm_ack[0]++;
// *** Need to handle data if any here.
// Let's reply with our on SYN and an ACK
// We should include a Max Recieve window0 option
xm_seq[1]++;
if (xm_seq[1] == 0)
xm_seq[0]++;
load_ethernet_header(); // 12 bytes (2 bytes for protocol included in load_IP..)
load_IP_header(48,TCP); // Number of bytes included in call (add 2 for protocol)
// 20 for IP header
// 20 for TCP header
// 8 for Options
load_TCP_header( 0x7000 | TCP_SYN | TCP_ACK, 0x07B8, 28);
// Number of bytes include in load_IP_header call
// Send options
myoutportb(NIC_DATA,0x02);
myoutportb(NIC_DATA,0x04);
myoutportb(NIC_DATA,0x05);
myoutportb(NIC_DATA,0xb4);
myoutportb(NIC_DATA,0x00);
myoutportb(NIC_DATA,0x00);
myoutportb(NIC_DATA,0x00);
myoutportb(NIC_DATA,0x00);
send_packet(62);
// Calculate the next sequence number to send
// In this case we add 1 since we only sent a SYN
xm_seq[1]++;
if (xm_seq[1] == 0)
xm_seq[0]++;
html_socket = SYN_RCVD;
}
// ********************************************************
void tcp_syn_rcvd(void) {
// Calculate data length
tcp_data_len = IP_length - (hdr_len + offset);
// Increment sequence to account for data
xm_ack[1] += tcp_data_len;
if (xm_ack[1] < seq[1] )
xm_ack[0]++;
// *** Need to handle data if any here.
// We'll assume there isn't any for now so no response is needed
html_socket = ESTAB;
}
// ********************************************************
void tcp_estab(void) {
tcp_data_len = IP_length - (hdr_len + offset);
// This is the next sequence number we expect
xm_ack[1] += tcp_data_len;
if (xm_ack[1] < seq[1] )
xm_ack[0]++;
// Let's cheat and send an HTML response
load_ethernet_header(); // 12 bytes (2 bytes for protocol included in load_IP..)
load_IP_header(188,TCP); // Number of bytes included in call (add 2 for protocol)
// 20 for IP header
// 20 for TCP header
// 148 for Data
load_TCP_header( 0x5000 | TCP_ACK | TCP_FIN, 0x07AC, 148);
// Number of bytes include in load_IP_header call
myoutportstr(NIC_DATA,"HTTP/1.0 200 OK\r\n"
"Content-type: text/html\r\n\r\n"
"<HTML><body>SimmStick® Web Server<br>"
"using a PIC 16F874<br>"
"by David C. Witt (12/24/00)</body></HTML>");
xm_ack[1] += 148;
if (xm_ack[1] < seq[1])
xm_ack[0]++;
send_packet(202);
html_socket = LISTEN;
}
// ********************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -