/[H8]/trunk/docs/Microchip TCP_IP stack/TCPIP Stack/DHCPs.c
ViewVC logotype

Contents of /trunk/docs/Microchip TCP_IP stack/TCPIP Stack/DHCPs.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 15 - (show annotations) (download)
Thu Apr 19 09:01:15 2007 UTC (17 years, 1 month ago) by hedin
File MIME type: text/plain
File size: 14138 byte(s)
added the TCP/IP stack, source code.
1 /*********************************************************************
2 *
3 * Dynamic Host Configuration Protocol (DHCP) Server
4 * Module for Microchip TCP/IP Stack
5 * -Provides automatic IP address, subnet mask, gateway address,
6 * DNS server address, and other configuration parameters on DHCP
7 * enabled networks.
8 * -Reference: RFC 2131, 2132
9 *
10 *********************************************************************
11 * FileName: DHCPs.c
12 * Dependencies: UDP, ARP, Tick
13 * Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F
14 * Complier: Microchip C18 v3.10 or higher
15 * Microchip C30 v2.05 or higher
16 * Company: Microchip Technology, Inc.
17 *
18 * Software License Agreement
19 *
20 * Copyright © 2002-2007 Microchip Technology Inc. All rights
21 * reserved.
22 *
23 * Microchip licenses to you the right to use, modify, copy, and
24 * distribute:
25 * (i) the Software when embedded on a Microchip microcontroller or
26 * digital signal controller product (“Device”) which is
27 * integrated into Licensee’s product; or
28 * (ii) ONLY the Software driver source files ENC28J60.c and
29 * ENC28J60.h ported to a non-Microchip device used in
30 * conjunction with a Microchip ethernet controller for the
31 * sole purpose of interfacing with the ethernet controller.
32 *
33 * You should refer to the license agreement accompanying this
34 * Software for additional information regarding your rights and
35 * obligations.
36 *
37 * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED “AS IS” WITHOUT
38 * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
39 * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
40 * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
41 * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
42 * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
43 * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
44 * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
45 * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
46 * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
47 * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
48 *
49 *
50 * Author Date Comment
51 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
52 * Howard Schlunder 02/28/07 Original
53 ********************************************************************/
54 #define __DHCPS_C
55
56 #include "TCPIP Stack/TCPIP.h"
57
58 #if defined(STACK_USE_DHCP_SERVER)
59
60 #define DHCP_LEASE_DURATION 10ul // Seconds. This is extremely short so the client(s) won't use our IP address for long if we inadvertently give out a DHCP lease while there is another DHCP server on this network that we didn't know about.
61 //#define DHCP_MAX_LEASES 2 // Not implemented
62
63 // ClientMAC multicast bit is used to determine if a lease is given out or not.
64 // Lease IP address is derived from index into DCB array
65 typedef struct _DHCP_CONTROL_BLOCK
66 {
67 TICK LeaseExpires;
68 MAC_ADDR ClientMAC;
69 enum
70 {
71 LEASE_UNUSED = 0,
72 LEASE_REQUESTED,
73 LEASE_GRANTED
74 } smLease;
75 } DHCP_CONTROL_BLOCK;
76
77
78 static UDP_SOCKET MySocket;
79 static IP_ADDR DHCPNextLease;
80 //static DHCP_CONTROL_BLOCK DCB[DHCP_MAX_LEASES]; // Not Implmented
81 BOOL bDHCPServerEnabled = TRUE;
82
83 static void DHCPReplyToDiscovery(BOOTP_HEADER *Header);
84 static void DHCPReplyToRequest(BOOTP_HEADER *Header, BOOL bAccept);
85
86
87 /*********************************************************************
88 * Function: void DHCPServerTask(void)
89 *
90 * PreCondition: None
91 *
92 * Input: None
93 *
94 * Output: Processes DHCP requests and distributes IP
95 * addresses
96 *
97 * Side Effects: None
98 *
99 * Overview: None
100 *
101 * Note: None
102 ********************************************************************/
103 void DHCPServerTask(void)
104 {
105 BYTE i;
106 BYTE Option, Len;
107 BOOTP_HEADER BOOTPHeader;
108 DWORD dw;
109 BOOL bAccept;
110 static enum
111 {
112 DHCP_OPEN_SOCKET,
113 DHCP_LISTEN
114 } smDHCPServer = DHCP_OPEN_SOCKET;
115
116 #if defined(STACK_USE_DHCP_CLIENT)
117 // Make sure we don't clobber anyone else's DHCP server
118 if(DHCPFlags.bits.bDHCPServerDetected)
119 return;
120 #endif
121
122 if(!bDHCPServerEnabled)
123 return;
124
125 switch(smDHCPServer)
126 {
127 case DHCP_OPEN_SOCKET:
128 // Obtain a UDP socket to listen/transmit on
129 MySocket = UDPOpen(DHCP_SERVER_PORT, NULL, DHCP_CLIENT_PORT);
130 if(MySocket == INVALID_UDP_SOCKET)
131 break;
132
133
134 // Decide which address to lease out
135 // Note that this needs to be changed if we are to
136 // support more than one lease
137 DHCPNextLease.Val = (AppConfig.MyIPAddr.Val & AppConfig.MyMask.Val) + 0x02000000;
138 if(DHCPNextLease.v[3] == 255)
139 DHCPNextLease.v[3] += 0x03000000;
140 if(DHCPNextLease.v[3] == 0)
141 DHCPNextLease.Val += 0x02000000;
142
143 smDHCPServer++;
144
145 case DHCP_LISTEN:
146 // Check to see if a valid DHCP packet has arrived
147 if(UDPIsGetReady(MySocket) < 241)
148 break;
149
150 // Retrieve the BOOTP header
151 UDPGetArray((BYTE*)&BOOTPHeader, sizeof(BOOTPHeader));
152
153 bAccept = (BOOTPHeader.ClientIP.Val == DHCPNextLease.Val) || (BOOTPHeader.ClientIP.Val == 0x00000000);
154
155 // Validate first three fields
156 if(BOOTPHeader.MessageType != 1u)
157 break;
158 if(BOOTPHeader.HardwareType != 1u)
159 break;
160 if(BOOTPHeader.HardwareLen != 6u)
161 break;
162
163 // Throw away 10 unused bytes of hardware address,
164 // server host name, and boot file name -- unsupported/not needed.
165 for(i = 0; i < 64+128+(16-sizeof(MAC_ADDR)); i++)
166 UDPGet(&Option);
167
168 // Obtain Magic Cookie and verify
169 UDPGetArray((BYTE*)&dw, sizeof(DWORD));
170 if(dw != 0x63538263ul)
171 break;
172
173 // Obtain options
174 while(1)
175 {
176 // Get option type
177 if(!UDPGet(&Option))
178 break;
179 if(Option == DHCP_END_OPTION)
180 break;
181
182 // Get option length
183 UDPGet(&Len);
184
185 // Process option
186 switch(Option)
187 {
188 case DHCP_MESSAGE_TYPE:
189 UDPGet(&i);
190 switch(i)
191 {
192 case DHCP_DISCOVER_MESSAGE:
193 DHCPReplyToDiscovery(&BOOTPHeader);
194 break;
195
196 case DHCP_REQUEST_MESSAGE:
197 DHCPReplyToRequest(&BOOTPHeader, bAccept);
198 break;
199
200 // Need to handle these if supporting more than one DHCP lease
201 case DHCP_RELEASE_MESSAGE:
202 case DHCP_DECLINE_MESSAGE:
203 break;
204 }
205 break;
206
207 case DHCP_PARAM_REQUEST_IP_ADDRESS:
208 if(Len == 4)
209 {
210 // Get the requested IP address and see if it is the one we have on offer.
211 UDPGetArray((BYTE*)&dw, 4);
212 bAccept = (dw == DHCPNextLease.Val);
213 }
214 break;
215
216 case DHCP_END_OPTION:
217 UDPDiscard();
218 return;
219 }
220
221 // Remove any unprocessed bytes that we don't care about
222 while(Len--)
223 {
224 UDPGet(&i);
225 }
226 }
227
228 UDPDiscard();
229 break;
230 }
231 }
232
233 static void DHCPReplyToDiscovery(BOOTP_HEADER *Header)
234 {
235 BYTE i;
236
237 // Set the correct socket to active and ensure that
238 // enough space is available to generate the DHCP response
239 if(UDPIsPutReady(MySocket) < 300)
240 return;
241
242 // Begin putting the BOOTP Header and DHCP options
243 UDPPut(BOOT_REPLY); // Message Type: 2 (BOOTP Reply)
244 // Reply with the same Hardware Type, Hardware Address Length, Hops, and Transaction ID fields
245 UDPPutArray((BYTE*)&(Header->HardwareType), 7);
246 UDPPut(0x00); // Seconds Elapsed: 0 (Not used)
247 UDPPut(0x00); // Seconds Elapsed: 0 (Not used)
248 UDPPutArray((BYTE*)&(Header->BootpFlags), sizeof(Header->BootpFlags));
249 UDPPut(0x00); // Your (client) IP Address: 0.0.0.0 (none yet assigned)
250 UDPPut(0x00); // Your (client) IP Address: 0.0.0.0 (none yet assigned)
251 UDPPut(0x00); // Your (client) IP Address: 0.0.0.0 (none yet assigned)
252 UDPPut(0x00); // Your (client) IP Address: 0.0.0.0 (none yet assigned)
253 UDPPutArray((BYTE*)&DHCPNextLease, sizeof(IP_ADDR)); // Lease IP address to give out
254 UDPPut(0x00); // Next Server IP Address: 0.0.0.0 (not used)
255 UDPPut(0x00); // Next Server IP Address: 0.0.0.0 (not used)
256 UDPPut(0x00); // Next Server IP Address: 0.0.0.0 (not used)
257 UDPPut(0x00); // Next Server IP Address: 0.0.0.0 (not used)
258 UDPPut(0x00); // Relay Agent IP Address: 0.0.0.0 (not used)
259 UDPPut(0x00); // Relay Agent IP Address: 0.0.0.0 (not used)
260 UDPPut(0x00); // Relay Agent IP Address: 0.0.0.0 (not used)
261 UDPPut(0x00); // Relay Agent IP Address: 0.0.0.0 (not used)
262 UDPPutArray((BYTE*)&(Header->ClientMAC), sizeof(MAC_ADDR)); // Client MAC address: Same as given by client
263 for(i = 0; i < 64+128+(16-sizeof(MAC_ADDR)); i++) // Remaining 10 bytes of client hardware address, server host name: Null string (not used)
264 UDPPut(0x00); // Boot filename: Null string (not used)
265 UDPPut(0x63); // Magic Cookie: 0x63538263
266 UDPPut(0x82); // Magic Cookie: 0x63538263
267 UDPPut(0x53); // Magic Cookie: 0x63538263
268 UDPPut(0x63); // Magic Cookie: 0x63538263
269
270 // Options: DHCP Offer
271 UDPPut(DHCP_MESSAGE_TYPE);
272 UDPPut(1);
273 UDPPut(DHCP_OFFER_MESSAGE);
274
275 // Option: Subnet Mask
276 UDPPut(DHCP_SUBNET_MASK);
277 UDPPut(sizeof(IP_ADDR));
278 UDPPutArray((BYTE*)&AppConfig.MyMask, sizeof(IP_ADDR));
279
280 // Option: Lease duration
281 UDPPut(DHCP_IP_LEASE_TIME);
282 UDPPut(4);
283 UDPPut((DHCP_LEASE_DURATION>>24) & 0xFF);
284 UDPPut((DHCP_LEASE_DURATION>>16) & 0xFF);
285 UDPPut((DHCP_LEASE_DURATION>>8) & 0xFF);
286 UDPPut((DHCP_LEASE_DURATION) & 0xFF);
287
288 // Option: Server identifier
289 UDPPut(DHCP_SERVER_IDENTIFIER);
290 UDPPut(sizeof(IP_ADDR));
291 UDPPutArray((BYTE*)&AppConfig.MyIPAddr, sizeof(IP_ADDR));
292
293 // Option: Router/Gateway address
294 UDPPut(DHCP_ROUTER);
295 UDPPut(sizeof(IP_ADDR));
296 UDPPutArray((BYTE*)&AppConfig.MyIPAddr, sizeof(IP_ADDR));
297
298 // No more options, mark ending
299 UDPPut(DHCP_END_OPTION);
300
301 // Transmit the packet
302 UDPFlush();
303 }
304
305
306 // TODO: Handle more than one DHCP lease
307 static void DHCPReplyToRequest(BOOTP_HEADER *Header, BOOL bAccept)
308 {
309 BYTE i;
310
311 // Set the correct socket to active and ensure that
312 // enough space is available to generate the DHCP response
313 if(UDPIsPutReady(MySocket) < 300)
314 return;
315
316 // Search through all remaining options and look for the Requested IP address field
317 // Obtain options
318 while(UDPIsGetReady(MySocket))
319 {
320 BYTE Option, Len;
321 DWORD dw;
322
323 // Get option type
324 if(!UDPGet(&Option))
325 break;
326 if(Option == DHCP_END_OPTION)
327 break;
328
329 // Get option length
330 UDPGet(&Len);
331
332 // Process option
333 if((Option == DHCP_PARAM_REQUEST_IP_ADDRESS) && (Len == 4))
334 {
335 // Get the requested IP address and see if it is the one we have on offer. If not, we should send back a NAK, but since there could be some other DHCP server offering this address, we'll just silently ignore this request.
336 UDPGetArray((BYTE*)&dw, 4);
337 if(dw != DHCPNextLease.Val)
338 {
339 bAccept = FALSE;
340 }
341 break;
342 }
343
344 // Remove the unprocessed bytes that we don't care about
345 while(Len--)
346 {
347 UDPGet(&i);
348 }
349 }
350
351
352 #if defined(STACK_USE_DHCP_CLIENT)
353 // Someone is using our DHCP server, start using a static
354 // IP address and update the bind count so it displays on
355 // the LCD
356 AppConfig.Flags.bInConfigMode = FALSE;
357 DHCPBindCount++;
358 #endif
359
360 // Begin putting the BOOTP Header and DHCP options
361 UDPPut(BOOT_REPLY); // Message Type: 2 (BOOTP Reply)
362 // Reply with the same Hardware Type, Hardware Address Length, Hops, and Transaction ID fields
363 UDPPutArray((BYTE*)&(Header->HardwareType), 7);
364 UDPPut(0x00); // Seconds Elapsed: 0 (Not used)
365 UDPPut(0x00); // Seconds Elapsed: 0 (Not used)
366 UDPPutArray((BYTE*)&(Header->BootpFlags), sizeof(Header->BootpFlags));
367 UDPPutArray((BYTE*)&(Header->ClientIP), sizeof(IP_ADDR));// Your (client) IP Address:
368 UDPPutArray((BYTE*)&DHCPNextLease, sizeof(IP_ADDR)); // Lease IP address to give out
369 UDPPut(0x00); // Next Server IP Address: 0.0.0.0 (not used)
370 UDPPut(0x00); // Next Server IP Address: 0.0.0.0 (not used)
371 UDPPut(0x00); // Next Server IP Address: 0.0.0.0 (not used)
372 UDPPut(0x00); // Next Server IP Address: 0.0.0.0 (not used)
373 UDPPut(0x00); // Relay Agent IP Address: 0.0.0.0 (not used)
374 UDPPut(0x00); // Relay Agent IP Address: 0.0.0.0 (not used)
375 UDPPut(0x00); // Relay Agent IP Address: 0.0.0.0 (not used)
376 UDPPut(0x00); // Relay Agent IP Address: 0.0.0.0 (not used)
377 UDPPutArray((BYTE*)&(Header->ClientMAC), sizeof(MAC_ADDR)); // Client MAC address: Same as given by client
378 for(i = 0; i < 64+128+(16-sizeof(MAC_ADDR)); i++) // Remaining 10 bytes of client hardware address, server host name: Null string (not used)
379 UDPPut(0x00); // Boot filename: Null string (not used)
380 UDPPut(0x63); // Magic Cookie: 0x63538263
381 UDPPut(0x82); // Magic Cookie: 0x63538263
382 UDPPut(0x53); // Magic Cookie: 0x63538263
383 UDPPut(0x63); // Magic Cookie: 0x63538263
384
385 // Options: DHCP lease ACKnowledge
386 if(bAccept)
387 {
388 UDPPut(DHCP_OPTION_ACK_MESSAGE);
389 UDPPut(1);
390 UDPPut(DHCP_ACK_MESSAGE);
391 }
392 else // Send a NACK
393 {
394 UDPPut(DHCP_OPTION_ACK_MESSAGE);
395 UDPPut(1);
396 UDPPut(DHCP_NAK_MESSAGE);
397 }
398
399 // Option: Lease duration
400 UDPPut(DHCP_IP_LEASE_TIME);
401 UDPPut(4);
402 UDPPut((DHCP_LEASE_DURATION>>24) & 0xFF);
403 UDPPut((DHCP_LEASE_DURATION>>16) & 0xFF);
404 UDPPut((DHCP_LEASE_DURATION>>8) & 0xFF);
405 UDPPut((DHCP_LEASE_DURATION) & 0xFF);
406
407 // Option: Server identifier
408 UDPPut(DHCP_SERVER_IDENTIFIER);
409 UDPPut(sizeof(IP_ADDR));
410 UDPPutArray((BYTE*)&AppConfig.MyIPAddr, sizeof(IP_ADDR));
411
412 // Option: Subnet Mask
413 UDPPut(DHCP_SUBNET_MASK);
414 UDPPut(sizeof(IP_ADDR));
415 UDPPutArray((BYTE*)&AppConfig.MyMask, sizeof(IP_ADDR));
416
417 // Option: Router/Gateway address
418 UDPPut(DHCP_ROUTER);
419 UDPPut(sizeof(IP_ADDR));
420 UDPPutArray((BYTE*)&AppConfig.MyIPAddr, sizeof(IP_ADDR));
421
422 // No more options, mark ending
423 UDPPut(DHCP_END_OPTION);
424
425 // Transmit the packet
426 UDPFlush();
427 }
428
429 #endif //#if defined(STACK_USE_DHCP_SERVER)

  ViewVC Help
Powered by ViewVC 1.1.20