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