📄 ip.lst
字号:
C51 COMPILER V7.09 IP 07/27/2007 15:11:24 PAGE 1
C51 COMPILER V7.09, COMPILATION OF MODULE IP
OBJECT MODULE PLACED IN IP.obj
COMPILER INVOKED BY: F:\Keil\C51\BIN\C51.EXE tcp\IP.C LARGE BROWSE DEBUG OBJECTEXTEND PRINT(.\IP.lst) OBJECT(IP.obj)
line level source
1 //-----------------------------------------------------------------------------
2 // Copyright (c) 2002 Jim Brady
3 // Do not use commercially without author's permission
4 // Last revised August 2002
5 // Net IP.C
6 //
7 // This module is the IP layer
8 // Refer to RFC 791, 1122, and RFC 815 (fragmentation)
9 //-----------------------------------------------------------------------------
10 #include "stdlib.h"
11 #include "net.h"
12 #include "cksum.h"
13 #include "arp.h"
14 #include "icmp.h"
15 #include "udp.h"
16 #include "eth.h"
17 #include "tcp.h"
18 #include "ip.h"
19 #include "utils.h"
20
21 extern UCHAR debug;
22 extern ulong my_ipaddr;
23 extern UCHAR broadcast_hwaddr[];
24 WAIT volatile wait;
25
26
27 //------------------------------------------------------------------------
28 // This handles outgoing IP datagrams. It adds the 20 byte IP header
29 // and checksum then forwards the IP datagram to the Ethernet layer
30 // for sending. See "TCP/IP Illustrated, Volume 1" Sect 3.2
31 //------------------------------------------------------------------------
32 void ip_send(UCHAR * outbuf, ulong ipaddr, UCHAR proto_id, uint len)
33 {
34 1 //UCHAR testadd[6]={0x00,0x19,0x21,0x5b,0xd8,0x3f};
35 1 IP_HEADER * ip;
36 1 UCHAR * hwaddr;
37 1 static uint ip_ident = 0;
38 1
39 1 ip = (IP_HEADER *)(outbuf + 14);
40 1 ip->ver_len = 0x45; //版本(=$4) + 首部长度(= $5 * 4 =20): IPv4 with 20 byte header
41 1 ip->type_of_service = 0; //服务类型:
42 1 ip->total_length = 20 + len; //总长度: 20 + len
43 1 ip->identifier = ip_ident++; //标识号: sequential identifier
44 1 ip->fragment_info = 0; //标志: 本案为不能分片; not fragmented
45 1 ip->time_to_live = 128; //生存时间: max hops
46 1 ip->protocol_id = proto_id; //上层协议: type of payload
47 1 ip->header_cksum = 0; //首部校验和:
48 1 ip->source_ipaddr = my_ipaddr;
49 1
50 1 // Outgoing IP address
51 1 ip->dest_ipaddr = ipaddr;
52 1
53 1 // Compute and insert complement of checksum of ip header
54 1 // Outgoing ip header length is always 20 bytes
55 1 ip->header_cksum = ~cksum(outbuf + 14, 20);
C51 COMPILER V7.09 IP 07/27/2007 15:11:24 PAGE 2
56 1
57 1 // Use ARP to get hardware address to send this to 通过ARP表取得目的主机的MAC地址;
58 1 hwaddr = arp_resolve(ip->dest_ipaddr);
59 1
60 1 // Null means that the ARP resolver did not find the IP address
61 1 // in its cache so had to send an ARP request
62 1 #ifdef __LITTLEENDIAN__
// hwaddr = testadd;
#endif
65 1 //没找到此IP地址对应MAC地址, 把欲发送的缓冲区信息和地址和端口等放入wait结构里,等找到时再发送
66 1
67 1 if (hwaddr == NULL)
68 1 { // Fill in the destination information so ehrn the ARP response
69 2 // arrives we can identify it and know what to do when we get it
70 2 if(ip->dest_ipaddr == 0xffffffff)
71 2 {
72 3 hwaddr = broadcast_hwaddr;
73 3 }
74 2 else
75 2 {
76 3 wait.buf = outbuf;
77 3 wait.ipaddr = ip->dest_ipaddr;
78 3 wait.proto_id = proto_id;
79 3 wait.len = len;
80 3 wait.timer = ARP_TIMEOUT;
81 3 return;
82 3 }
83 2 }
84 1
85 1 #ifdef __LITTLEENDIAN__
ip->dest_ipaddr = ntohl(ip->dest_ipaddr);
ip->source_ipaddr = ntohl(ip->source_ipaddr);
ip->total_length = ntohs(ip->total_length);
ip->identifier = ntohs(ip->identifier);
ip->header_cksum = 0;
ip->header_cksum = ~cksum(outbuf + 14, 20);
ip->header_cksum = ntohs(ip->header_cksum);
#endif
94 1
95 1 eth_send(outbuf, hwaddr, IP_PACKET, 20 + len);
96 1 }
97
98
99
100 //------------------------------------------------------------------------
101 // This handles incoming IP datagrams from the Ethernet layer
102 // See "TCP/IP Illustrated, Volume 1" Sect 3.2
103 //------------------------------------------------------------------------
104 void ip_rcve(UCHAR * inbuf)
105 {
106 1 IP_HEADER * ip;
107 1 uint header_len, payload_len;
108 1
109 1 ip = (IP_HEADER *)(inbuf + 14);
110 1
111 1 // Make sure it is addressed to my IP address
112 1 //目的IP地址不匹配, 返回
113 1 #ifdef __LITTLEENDIAN__
ip->total_length = ntohs(ip->total_length);
ip->dest_ipaddr = ntohl(ip->dest_ipaddr);
#endif
117 1 if (ip->dest_ipaddr != my_ipaddr)
C51 COMPILER V7.09 IP 07/27/2007 15:11:24 PAGE 3
118 1 return;
119 1
120 1 // Validate checksum of ip header
121 1 header_len = 4 * (0x0F & ip->ver_len); //计算首部长度
122 1 payload_len = ip->total_length - header_len; //计算静负荷长度
123 1 #ifdef __LITTLEENDIAN__
ip->total_length = ntohs(ip->total_length);
ip->dest_ipaddr = ntohl(ip->dest_ipaddr);
#endif
127 1
128 1 if (cksum(inbuf + 14, header_len) != 0xFFFF) //计算首部校验和, 不等于0xFFFF就丢弃;
129 1 {
130 2 //if (debug) serial_send("IP: Error, cksum bad\r");
131 2 return;
132 2 }
133 1 #ifdef __LITTLEENDIAN__
ip->total_length = ntohs(ip->total_length);
ip->fragment_info = ntohs(ip->fragment_info);
ip->dest_ipaddr = ntohl(ip->dest_ipaddr);
ip->source_ipaddr = ntohl(ip->source_ipaddr);
ip->header_cksum = ntohs(ip->header_cksum);
#endif
140 1 // Make sure incoming message is IP version 4
141 1 if ((ip->ver_len >> 4) != 0x04) //不支持非版本4
142 1 {
143 2 //if (debug) serial_send("IP: Error, not IPv4\r");
144 2 return;
145 2 }
146 1
147 1 // Make sure incoming message is not fragmented because
148 1 // we cannot handle fragmented messages
149 1 // 不支持分片IP包;
150 1 if ((ip->fragment_info & 0x3FFF) != 0)
151 1 {
152 2 //if (debug) serial_send("IP: Error, fragmented msg rcvd\r");
153 2 return;
154 2 }
155 1
156 1 // At this point we have received a valid IP datagram addressed
157 1 // to me. We do not use header options, and do not forward
158 1 // messages, so in the unlikely event there are header options,
159 1 // delete them and shift the data down. The advantage is that
160 1 // layers such as UDP and TCP know where their data starts
161 1
162 1 //如果首部长度 > 20, 即存在可变部分, 把净负荷数据移到从固定部分20字节开始.
163 1 if (header_len > 20)
164 1 {
165 2 //if (debug) serial_send("IP: Rcvd header > 20 bytes\r");
166 2
167 2 // Use memmove because of overlap
168 2 // memmove(inbuf + 34, inbuf + 14 + header_len, payload_len);
169 2 memcpy(inbuf + 34, inbuf + 14 + header_len, payload_len);
170 2
171 2 // Adjust info to reflect the move
172 2 header_len = 20;
173 2 ip->ver_len = 0x45;
174 2 ip->total_length = 20 + payload_len;
175 2 }
176 1
177 1
178 1 // Look at protocol ID byte and call the appropriate
179 1 // function to handle the received message. See
C51 COMPILER V7.09 IP 07/27/2007 15:11:24 PAGE 4
180 1 // "TCP/IP Illustrated, Volume 1" Sect 1.7 and RFC 791
181 1 // for values for various protocols
182 1
183 1 //按上层协议号,分别提交给上层不同协议进程处理;
184 1 switch (ip->protocol_id)
185 1 {
186 2 case ICMP_TYPE:
187 2 //if (debug)
188 2 // serial_send("IP: ICMP pkt rcvd\n");
189 2 icmp_rcve(inbuf, payload_len);
190 2 break;
191 2
192 2 case IGMP_TYPE:
193 2 // We cannot handle IGMP messages
194 2 //if (debug)
195 2 // serial_send("IP: Error, IGMP pkt rcvd\n");
196 2 break;
197 2
198 2 case UDP_TYPE:
199 2 //if (debug)
200 2 #ifdef __LITTLEENDIAN__
ip->total_length = ntohs(ip->total_length);
ip->fragment_info = ntohs(ip->fragment_info);
ip->dest_ipaddr = ntohl(ip->dest_ipaddr);
ip->source_ipaddr = ntohl(ip->source_ipaddr);
ip->header_cksum = ntohs(ip->header_cksum);
#endif
207 2
208 2 // serial_send("IP: UDP pkt rcvd\n");
209 2 udp_rcve(inbuf, payload_len);
210 2 break;
211 2
212 2 case TCP_TYPE:
213 2 // if (debug)
214 2 // serial_send("IP: TCP pkt rcvd\n");
215 2 #ifdef __LITTLEENDIAN__
ip->total_length = ntohs(ip->total_length);
ip->fragment_info = ntohs(ip->fragment_info);
ip->dest_ipaddr = ntohl(ip->dest_ipaddr);
ip->source_ipaddr = ntohl(ip->source_ipaddr);
ip->header_cksum = ntohs(ip->header_cksum);
#endif
222 2 tcp_rcve(inbuf, payload_len);
223 2 break;
224 2
225 2 default:
226 2 // if (debug) serial_send("IP: Unknown IP proto id rcvd\r");
227 2 break;
228 2 }
229 1 }
230
231
232
MODULE INFORMATION: STATIC OVERLAYABLE
CODE SIZE = 874 ----
CONSTANT SIZE = ---- ----
XDATA SIZE = 13 26
PDATA SIZE = ---- ----
DATA SIZE = ---- ----
IDATA SIZE = ---- ----
C51 COMPILER V7.09 IP 07/27/2007 15:11:24 PAGE 5
BIT SIZE = ---- ----
END OF MODULE INFORMATION.
C51 COMPILATION COMPLETE. 0 WARNING(S), 0 ERROR(S)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -