📄 arp.lst
字号:
C51 COMPILER V7.06 ARP 10/09/2006 21:51:54 PAGE 1
C51 COMPILER V7.06, COMPILATION OF MODULE ARP
OBJECT MODULE PLACED IN arp.OBJ
COMPILER INVOKED BY: D:\Program Files\Keil\C51\BIN\C51.EXE arp.c BROWSE DEBUG OBJECTEXTEND
stmt level source
1 //-----------------------------------------------------------------------------
2 // Net ARP.C
3 //
4 // This module handles ARP messages and ARP resolution and manages
5 // the ARP cache. Refer to RFC 826 and RFC 1122
6 //-----------------------------------------------------------------------------
7 #include <general.h>
8
9
10
11 extern UCHAR code broadcast_hwaddr[];
12 extern WAIT xdata wait;
13 extern UCHAR code my_hwaddr[];
14 extern ULONG code my_ipaddr;
15 extern ULONG code my_subnet;
16 extern ULONG code gateway_ipaddr;
17 ARP_CACHE xdata arp_cache[CACHESIZE];
18 UCHAR waiting_for_arp;
19
20
21
22 void init_arp(void)
23 {
24 1 memset(arp_cache, 0, sizeof(arp_cache));
25 1 memset(&wait, 0, sizeof(wait));
26 1 waiting_for_arp = FALSE;
27 1 }
28
29
30
31
32 //------------------------------------------------------------------------
33 // This is called every 60 seconds to age the ARP cache
34 // If an entry times out then it is deleted from the cache
35 // See "TCP/IP Illustrated, Volume 1" Sect 4.3
36 //------------------------------------------------------------------------
37 void age_arp_cache(void)
38 {
39 1 UCHAR i;
40 1
41 1 for (i=0; i < CACHESIZE; i++)
42 1 {
43 2 if ((arp_cache[i].ipaddr != 0) && (arp_cache[i].timer))
44 2 {
45 3 arp_cache[i].timer--;
46 3 if (arp_cache[i].timer == 0)
47 3 {
48 4 // Timed out so clear out cache entry
49 4 // Do not need to zero hwaddr
50 4 arp_cache[i].ipaddr = 0;
51 4
52 4 }
53 3 }
54 2 }
55 1 }
C51 COMPILER V7.06 ARP 10/09/2006 21:51:54 PAGE 2
56
57
58
59
60 //------------------------------------------------------------------------
61 // This allocates memory for the entire outgoing message,
62 // including eth and ip headers, then builds an outgoing
63 // ARP response message
64 // See "TCP/IP Illustrated, Volume 1" Sect 4.4
65 //------------------------------------------------------------------------
66 void arp_send(UCHAR * hwaddr, ULONG ipaddr, UCHAR msg_type)
67 {
68 1 UCHAR xdata * outbuf;
69 1 ARP_HEADER xdata * arp;
70 1
71 1
72 1 // Allocate memory for entire outgoing message including
73 1 // eth header. Always 42 bytes
74 1 outbuf = (UCHAR xdata *)malloc(42);
75 1 if (outbuf == NULL)
76 1 {
77 2
78 2 return;
79 2 }
80 1
81 1 // Allow 14 bytes for the ethernet header
82 1 arp = (ARP_HEADER xdata *)(outbuf + 14);
83 1
84 1 arp->hardware_type = DIX_ETHERNET;
85 1 arp->protocol_type = IP_PACKET;
86 1 arp->hwaddr_len = 6;
87 1 arp->ipaddr_len = 4;
88 1 arp->message_type = (UINT)msg_type;
89 1
90 1 // My hardware address and IP addresses
91 1 memcpy(arp->source_hwaddr, my_hwaddr, 6);
92 1 arp->source_ipaddr = my_ipaddr;
93 1
94 1 // Destination hwaddr and dest IP addr
95 1 if (msg_type == ARP_REQUEST) memset(arp->dest_hwaddr, 0, 6);
96 1 else memcpy(arp->dest_hwaddr, hwaddr, 6);
97 1
98 1 arp->dest_ipaddr = ipaddr;
99 1
100 1 // If request then the message is a brodcast, if a response then
101 1 // send to specified hwaddr
102 1 // ARP payload size is always 28 bytes
103 1 if (msg_type == ARP_REQUEST) eth_send(outbuf, broadcast_hwaddr, ARP_PACKET, 28);
104 1 else eth_send(outbuf, hwaddr, ARP_PACKET, 28);
105 1 }
106
107
108
109 //------------------------------------------------------------------------
110 // This re-sends an ARP request if there was no response to
111 // the first one. It is called every 0.5 seconds. If there
112 // is no response after 2 re-tries, the datagram that IP was
113 // trying to send is deleted
114 //-----------------------------------------------------------------------
115 void arp_retransmit(void)
116 {
117 1 static UCHAR idata retries = 0;
C51 COMPILER V7.06 ARP 10/09/2006 21:51:54 PAGE 3
118 1
119 1 if ((waiting_for_arp) && (wait.timer))
120 1 {
121 2 wait.timer--;
122 2 if (wait.timer == 0)
123 2 {
124 3 retries++;
125 3 if (retries <= 2)
126 3 {
127 4
128 4 arp_send(NULL, wait.ipaddr, ARP_REQUEST);
129 4 wait.timer = ARP_TIMEOUT;
130 4 }
131 3 else
132 3 {
133 4
134 4 wait.timer = 0;
135 4 waiting_for_arp = 0;
136 4 free(wait.buf);
137 4 }
138 3 }
139 2 }
140 1 }
141
142
143
144
145 //------------------------------------------------------------------------
146 // Find the ethernet hardware address for the given ip address
147 // If destination IP is on my subnet then we want the eth
148 // address of destination, otherwise we want eth addr of gateway.
149 // Look in ARP cache first. If not found there, send ARP request.
150 // Return pointer to the hardware address or NULL if not found
151 // See "TCP/IP Illustrated, Volume 1" Sect 4.5
152 //------------------------------------------------------------------------
153 UCHAR xdata * arp_resolve(ULONG dest_ipaddr)
154 {
155 1 UCHAR i;
156 1
157 1 // If destination IP is not on my subnet then we really want eth addr
158 1 // of gateway, not destination IP
159 1 if ((dest_ipaddr ^ my_ipaddr) & my_subnet)
160 1 {
161 2 if (gateway_ipaddr == 0)
162 2 {
163 3 return (NULL);
164 3 }
165 2 else dest_ipaddr = gateway_ipaddr;
166 2 }
167 1
168 1
169 1 // See if IP addr of interest is in ARP cache
170 1 for (i=0; i < CACHESIZE; i++)
171 1 {
172 2 if (arp_cache[i].ipaddr == dest_ipaddr)
173 2 return (&arp_cache[i].hwaddr[0]);
174 2 }
175 1
176 1 // Not in cache so broadcast ARP request
177 1 arp_send(NULL, dest_ipaddr, ARP_REQUEST);
178 1
179 1 // Set a flag to indicate that an IP datagram is waiting
C51 COMPILER V7.06 ARP 10/09/2006 21:51:54 PAGE 4
180 1 // to be sent
181 1 waiting_for_arp = TRUE;
182 1
183 1 // Null means that we have sent an ARP request
184 1 return (NULL);
185 1 }
186
187
188
189
190
191 //------------------------------------------------------------------------
192 // This handles incoming ARP messages
193 // See "TCP/IP Illustrated, Volume 1" Sect 4.4
194 // Todo: Resolve problem of trying to add to a full cache
195 //------------------------------------------------------------------------
196 void arp_rcve(UCHAR xdata * inbuf)
197 {
198 1 UCHAR idata i, cached, oldest;
199 1 UINT idata minimum;
200 1 ARP_HEADER xdata * arp;
201 1
202 1 arp = (ARP_HEADER xdata *)(inbuf + 14);
203 1 cached = FALSE;
204 1
205 1
206 1 // Validate incoming frame
207 1 if ((arp->hardware_type != DIX_ETHERNET) ||
208 1 (arp->protocol_type != IP_PACKET)) return;
209 1
210 1 // Search ARP cache for senders IP address
211 1 // If found, update entry and restart timer
212 1 for (i=0; i < CACHESIZE; i++)
213 1 {
214 2 if (arp_cache[i].ipaddr == arp->source_ipaddr)
215 2 {
216 3 memcpy(&arp_cache[i].hwaddr[0], &arp->source_hwaddr[0], 6);
217 3 arp_cache[i].timer = CACHETIME;
218 3
219 3
220 3 break;
221 3 }
222 2 }
223 1
224 1 if (arp->dest_ipaddr != my_ipaddr) return;
225 1
226 1 // At this point we know the the frame is addressed to me
227 1 // If not already in cache then add entry and start timer
228 1 if (cached == FALSE)
229 1 {
230 2 // Find first blank space and add entry
231 2 // Blank entries are indicated by ip addr = 0
232 2 for (i=0; i < CACHESIZE; i++)
233 2 {
234 3 if (arp_cache[i].ipaddr == 0)
235 3 {
236 4 arp_cache[i].ipaddr = arp->source_ipaddr;
237 4 memcpy(&arp_cache[i].hwaddr[0], &arp->source_hwaddr[0], 6);
238 4 arp_cache[i].timer = CACHETIME;
239 4 break;
240 4 }
241 3 }
C51 COMPILER V7.06 ARP 10/09/2006 21:51:54 PAGE 5
242 2
243 2 // If no blank entries in arp cache then sort cache
244 2 // to find oldest entry and replace it
245 2 if (i == CACHESIZE)
246 2 {
247 3 // Oldest entry is the one with lowest timer value
248 3 minimum = 0xFFFF;
249 3 for (i=0; i < CACHESIZE; i++)
250 3 {
251 4 if (arp_cache[i].timer < minimum)
252 4 {
253 5 minimum = arp_cache[i].timer;
254 5 oldest = i;
255 5 }
256 4 }
257 3
258 3 // "oldest" is now index of oldest entry, so replace it
259 3 arp_cache[oldest].ipaddr = arp->source_ipaddr;
260 3 memcpy(&arp_cache[oldest].hwaddr[0], &arp->source_hwaddr[0], 6);
261 3 arp_cache[oldest].timer = CACHETIME;
262 3
263 3 }
264 2 }
265 1
266 1
267 1 // If we are waiting for an arp response and the arp response
268 1 // that just came in is addressed to me and is from the host
269 1 // we are waiting for, then send the message-in-waiting
270 1 if (arp->message_type == ARP_RESPONSE)
271 1 {
272 2 if ((waiting_for_arp) && (wait.ipaddr == arp->source_ipaddr))
273 2 {
274 3 waiting_for_arp = FALSE;
275 3 ip_send(wait.buf, wait.ipaddr, wait.proto_id, wait.len);
276 3 }
277 2 }
278 1 else if (arp->message_type == ARP_REQUEST)
279 1 {
280 2 // Send ARP response
281 2 arp_send(arp->source_hwaddr, arp->source_ipaddr, ARP_RESPONSE);
282 2 }
283 1 }
284
MODULE INFORMATION: STATIC OVERLAYABLE
CODE SIZE = 1442 ----
CONSTANT SIZE = ---- ----
XDATA SIZE = 110 ----
PDATA SIZE = ---- ----
DATA SIZE = 1 20
IDATA SIZE = 1 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 + -