?? ip1.lst
字號:
C51 COMPILER V7.09 IP1 06/28/2007 09:51:21 PAGE 1
C51 COMPILER V7.09, COMPILATION OF MODULE IP1
OBJECT MODULE PLACED IN IP1.obj
COMPILER INVOKED BY: F:\Keil\C51\BIN\C51.EXE tcp\IP1.C LARGE BROWSE DEBUG OBJECTEXTEND PRINT(.\IP1.lst) OBJECT(IP1.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 "net1.h"
12 #include "cksum.h"
13 #include "arp1.h"
14 #include "icmp1.h"
15 #include "udp1.h"
16 #include "eth1.h"
17 #include "tcp1.h"
18 #include "ip1.h"
19 #include "utils.h"
20
21 extern UCHAR debug;
22 extern ulong my_ipaddr;
23 WAIT wait;
24
25
26 //------------------------------------------------------------------------
27 // This handles outgoing IP datagrams. It adds the 20 byte IP header
28 // and checksum then forwards the IP datagram to the Ethernet layer
29 // for sending. See "TCP/IP Illustrated, Volume 1" Sect 3.2
30 //------------------------------------------------------------------------
31 void ip_send1(UCHAR * outbuf, ulong ipaddr, UCHAR proto_id, uint len)
32 {
33 1 //UCHAR testadd[6]={0x00,0x19,0x21,0x5b,0xd8,0x3f};
34 1 IP_HEADER * ip;
35 1 UCHAR * hwaddr;
36 1 static uint ip_ident = 0;
37 1
38 1 ip = (IP_HEADER *)(outbuf + 14);
39 1 ip->ver_len = 0x45; //版本(=$4) + 首部長度(= $5 * 4 =20): IPv4 with 20 byte header
40 1 ip->type_of_service = 0; //服務(wù)類型:
41 1 ip->total_length = 20 + len; //總長度: 20 + len
42 1 ip->identifier = ip_ident++; //標(biāo)識號: sequential identifier
43 1 ip->fragment_info = 0; //標(biāo)志: 本案為不能分片; not fragmented
44 1 ip->time_to_live = 128; //生存時間: max hops
45 1 ip->protocol_id = proto_id; //上層協(xié)議: type of payload
46 1 ip->header_cksum = 0; //首部校驗和:
47 1 ip->source_ipaddr = my_ipaddr;
48 1
49 1 // Outgoing IP address
50 1 ip->dest_ipaddr = ipaddr;
51 1
52 1 // Compute and insert complement of checksum of ip header
53 1 // Outgoing ip header length is always 20 bytes
54 1 ip->header_cksum = ~cksum(outbuf + 14, 20);
55 1
C51 COMPILER V7.09 IP1 06/28/2007 09:51:21 PAGE 2
56 1 // Use ARP to get hardware address to send this to 通過ARP表取得目的主機的MAC地址;
57 1 hwaddr = arp_resolve(ip->dest_ipaddr);
58 1
59 1 // Null means that the ARP resolver did not find the IP address
60 1 // in its cache so had to send an ARP request
61 1 #ifdef __LITTLEENDIAN__
62 1 // hwaddr = testadd;
63 1 #endif
64 1 //沒找到此IP地址對應(yīng)MAC地址, 把欲發(fā)送的緩沖區(qū)信息和地址和端口等放入wait結(jié)構(gòu)里,等找到時再發(fā)送
65 1 if (hwaddr == NULL)
66 1 {
67 2 // Fill in the destination information so ehrn the ARP response
68 2 // arrives we can identify it and know what to do when we get it
69 2 wait.buf = outbuf;
70 2 wait.ipaddr = ip->dest_ipaddr;
71 2 wait.proto_id = proto_id;
72 2 wait.len = len;
73 2 wait.timer = ARP_TIMEOUT;
74 2 return;
75 2 }
76 1
77 1 #ifdef __LITTLEENDIAN__
78 1 ip->dest_ipaddr = ntohl(ip->dest_ipaddr);
79 1 ip->source_ipaddr = ntohl(ip->source_ipaddr);
80 1 ip->total_length = ntohs(ip->total_length);
81 1 ip->identifier = ntohs(ip->identifier);
82 1 ip->header_cksum = 0;
83 1 ip->header_cksum = ~cksum(outbuf + 14, 20);
84 1 ip->header_cksum = ntohs(ip->header_cksum);
85 1 #endif
86 1
87 1 eth_send1(outbuf, hwaddr, IP_PACKET, 20 + len);
88 1 }
89
90
91
92 //------------------------------------------------------------------------
93 // This handles incoming IP datagrams from the Ethernet layer
94 // See "TCP/IP Illustrated, Volume 1" Sect 3.2
95 //------------------------------------------------------------------------
96 void ip_rcve(UCHAR * inbuf)
97 {
98 1 IP_HEADER * ip;
99 1 uint header_len, payload_len;
100 1
101 1 ip = (IP_HEADER *)(inbuf + 14);
102 1
103 1 // Make sure it is addressed to my IP address
104 1 //目的IP地址不匹配, 返回
105 1 #ifdef __LITTLEENDIAN__
106 1 ip->total_length = ntohs(ip->total_length);
107 1 ip->dest_ipaddr = ntohl(ip->dest_ipaddr);
108 1 #endif
109 1 if (ip->dest_ipaddr != my_ipaddr)
110 1 return;
111 1
112 1 // Validate checksum of ip header
113 1 header_len = 4 * (0x0F & ip->ver_len); //計算首部長度
114 1 payload_len = ip->total_length - header_len; //計算靜負(fù)荷長度
115 1 #ifdef __LITTLEENDIAN__
116 1 ip->total_length = ntohs(ip->total_length);
117 1 ip->dest_ipaddr = ntohl(ip->dest_ipaddr);
C51 COMPILER V7.09 IP1 06/28/2007 09:51:21 PAGE 3
118 1 #endif
119 1
120 1 if (cksum(inbuf + 14, header_len) != 0xFFFF) //計算首部校驗和, 不等于0xFFFF就丟棄;
121 1 {
122 2 //if (debug) serial_send("IP: Error, cksum bad\r");
123 2 return;
124 2 }
125 1 #ifdef __LITTLEENDIAN__
126 1 ip->total_length = ntohs(ip->total_length);
127 1 ip->fragment_info = ntohs(ip->fragment_info);
128 1 ip->dest_ipaddr = ntohl(ip->dest_ipaddr);
129 1 ip->source_ipaddr = ntohl(ip->source_ipaddr);
130 1 ip->header_cksum = ntohs(ip->header_cksum);
131 1 #endif
132 1 // Make sure incoming message is IP version 4
133 1 if ((ip->ver_len >> 4) != 0x04) //不支持非版本4
134 1 {
135 2 //if (debug) serial_send("IP: Error, not IPv4\r");
136 2 return;
137 2 }
138 1
139 1 // Make sure incoming message is not fragmented because
140 1 // we cannot handle fragmented messages
141 1 // 不支持分片IP包;
142 1 if ((ip->fragment_info & 0x3FFF) != 0)
143 1 {
144 2 //if (debug) serial_send("IP: Error, fragmented msg rcvd\r");
145 2 return;
146 2 }
147 1
148 1 // At this point we have received a valid IP datagram addressed
149 1 // to me. We do not use header options, and do not forward
150 1 // messages, so in the unlikely event there are header options,
151 1 // delete them and shift the data down. The advantage is that
152 1 // layers such as UDP and TCP know where their data starts
153 1
154 1 //如果首部長度 > 20, 即存在可變部分, 把凈負(fù)荷數(shù)據(jù)移到從固定部分20字節(jié)開始.
155 1 if (header_len > 20)
156 1 {
157 2 //if (debug) serial_send("IP: Rcvd header > 20 bytes\r");
158 2
159 2 // Use memmove because of overlap
160 2 // memmove(inbuf + 34, inbuf + 14 + header_len, payload_len);
161 2 memcpy(inbuf + 34, inbuf + 14 + header_len, payload_len);
162 2
163 2 // Adjust info to reflect the move
164 2 header_len = 20;
165 2 ip->ver_len = 0x45;
166 2 ip->total_length = 20 + payload_len;
167 2 }
168 1
169 1
170 1 // Look at protocol ID byte and call the appropriate
171 1 // function to handle the received message. See
172 1 // "TCP/IP Illustrated, Volume 1" Sect 1.7 and RFC 791
173 1 // for values for various protocols
174 1
175 1 //按上層協(xié)議號,分別提交給上層不同協(xié)議進(jìn)程處理;
176 1 switch (ip->protocol_id)
177 1 {
178 2 case ICMP_TYPE:
179 2 //if (debug)
C51 COMPILER V7.09 IP1 06/28/2007 09:51:21 PAGE 4
180 2 // serial_send("IP: ICMP pkt rcvd\n");
181 2 icmp_rcve(inbuf, payload_len);
182 2 break;
183 2
184 2 case IGMP_TYPE:
185 2 // We cannot handle IGMP messages
186 2 //if (debug)
187 2 // serial_send("IP: Error, IGMP pkt rcvd\n");
188 2 break;
189 2
190 2 case UDP_TYPE:
191 2 //if (debug)
192 2 #ifdef __LITTLEENDIAN__
193 2 ip->total_length = ntohs(ip->total_length);
194 2 ip->fragment_info = ntohs(ip->fragment_info);
195 2 ip->dest_ipaddr = ntohl(ip->dest_ipaddr);
196 2 ip->source_ipaddr = ntohl(ip->source_ipaddr);
197 2 ip->header_cksum = ntohs(ip->header_cksum);
198 2 #endif
199 2
200 2 // serial_send("IP: UDP pkt rcvd\n");
201 2 udp_rcve(inbuf, payload_len);
202 2 break;
203 2
204 2 case TCP_TYPE:
205 2 // if (debug)
206 2 // serial_send("IP: TCP pkt rcvd\n");
207 2 #ifdef __LITTLEENDIAN__
208 2 ip->total_length = ntohs(ip->total_length);
209 2 ip->fragment_info = ntohs(ip->fragment_info);
210 2 ip->dest_ipaddr = ntohl(ip->dest_ipaddr);
211 2 ip->source_ipaddr = ntohl(ip->source_ipaddr);
212 2 ip->header_cksum = ntohs(ip->header_cksum);
213 2 #endif
214 2 tcp_rcve(inbuf, payload_len);
215 2 break;
216 2
217 2 default:
218 2 // if (debug) serial_send("IP: Unknown IP proto id rcvd\r");
219 2 break;
220 2 }
221 1 }
222
223
224
MODULE INFORMATION: STATIC OVERLAYABLE
CODE SIZE = 1748 ----
CONSTANT SIZE = ---- ----
XDATA SIZE = 11 24
PDATA SIZE = ---- ----
DATA SIZE = ---- ----
IDATA SIZE = ---- ----
BIT SIZE = ---- ----
END OF MODULE INFORMATION.
C51 COMPILATION COMPLETE. 0 WARNING(S), 0 ERROR(S)
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -