?lang_form? ?lang_select? ?lang_submit? ?lang_endform?
{HEADER END}
{BLAME START}

library

?curdirlinks? -

Blame information for rev 32

Line No. Rev Author Line
1 32 kaklik /*********************************************************************
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, PIC32
14 * Compiler: Microchip C32 v1.05 or higher
15 * Microchip C30 v3.12 or higher
16 * Microchip C18 v3.30 or higher
17 * HI-TECH PICC-18 PRO 9.63PL2 or higher
18 * Company: Microchip Technology, Inc.
19 *
20 * Software License Agreement
21 *
22 * Copyright (C) 2002-2009 Microchip Technology Inc. All rights
23 * reserved.
24 *
25 * Microchip licenses to you the right to use, modify, copy, and
26 * distribute:
27 * (i) the Software when embedded on a Microchip microcontroller or
28 * digital signal controller product ("Device") which is
29 * integrated into Licensee's product; or
30 * (ii) ONLY the Software driver source files ENC28J60.c, ENC28J60.h,
31 * ENCX24J600.c and ENCX24J600.h ported to a non-Microchip device
32 * used in conjunction with a Microchip ethernet controller for
33 * the sole purpose of interfacing with the ethernet controller.
34 *
35 * You should refer to the license agreement accompanying this
36 * Software for additional information regarding your rights and
37 * obligations.
38 *
39 * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
40 * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
41 * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
42 * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
43 * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
44 * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
45 * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
46 * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
47 * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
48 * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
49 * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
50 *
51 *
52 * Author Date Comment
53 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
54 * Howard Schlunder 02/28/07 Original
55 ********************************************************************/
56 #define __DHCPS_C
57  
58 #include "TCPIPConfig.h"
59  
60 #if defined(STACK_USE_DHCP_SERVER)
61  
62 #include "TCPIP Stack/TCPIP.h"
63  
64 // Duration of our DHCP Lease in seconds. This is extrememly short so
65 // the client won't use our IP for long if we inadvertantly
66 // provide a lease on a network that has a more authoratative DHCP server.
67 #define DHCP_LEASE_DURATION 60ul
68 /// Ignore: #define DHCP_MAX_LEASES 2 // Not implemented
69  
70 // DHCP Control Block. Lease IP address is derived from index into DCB array.
71 typedef struct
72 {
73 DWORD LeaseExpires; // Expiration time for this lease
74 MAC_ADDR ClientMAC; // Client's MAC address. Multicase bit is used to determine if a lease is given out or not
75 enum
76 {
77 LEASE_UNUSED = 0,
78 LEASE_REQUESTED,
79 LEASE_GRANTED
80 } smLease; // Status of this lease
81 } DHCP_CONTROL_BLOCK;
82  
83 static UDP_SOCKET MySocket; // Socket used by DHCP Server
84 static IP_ADDR DHCPNextLease; // IP Address to provide for next lease
85 /// Ignore: static DHCP_CONTROL_BLOCK DCB[DHCP_MAX_LEASES]; // Not Implmented
86 BOOL bDHCPServerEnabled = TRUE; // Whether or not the DHCP server is enabled
87  
88 static void DHCPReplyToDiscovery(BOOTP_HEADER *Header);
89 static void DHCPReplyToRequest(BOOTP_HEADER *Header, BOOL bAccept);
90  
91  
92 /*****************************************************************************
93 Function:
94 void DHCPServerTask(void)
95  
96 Summary:
97 Performs periodic DHCP server tasks.
98  
99 Description:
100 This function performs any periodic tasks requied by the DHCP server
101 module, such as processing DHCP requests and distributing IP addresses.
102  
103 Precondition:
104 None
105  
106 Parameters:
107 None
108  
109 Returns:
110 None
111 ***************************************************************************/
112 void DHCPServerTask(void)
113 {
114 BYTE i;
115 BYTE Option, Len;
116 BOOTP_HEADER BOOTPHeader;
117 DWORD dw;
118 BOOL bAccept;
119 static enum
120 {
121 DHCP_OPEN_SOCKET,
122 DHCP_LISTEN
123 } smDHCPServer = DHCP_OPEN_SOCKET;
124  
125 #if defined(STACK_USE_ZEROCONF_LINK_LOCAL)
126 static BOOL bLeaseAvailable = TRUE;
127 #endif
128  
129 #if defined(STACK_USE_DHCP_CLIENT)
130 // Make sure we don't clobber anyone else's DHCP server
131 if(DHCPIsServerDetected(0))
132 return;
133 #endif
134  
135 if(!bDHCPServerEnabled)
136 return;
137  
138 switch(smDHCPServer)
139 {
140 case DHCP_OPEN_SOCKET:
141 // Obtain a UDP socket to listen/transmit on
142 MySocket = UDPOpen(DHCP_SERVER_PORT, NULL, DHCP_CLIENT_PORT);
143 if(MySocket == INVALID_UDP_SOCKET)
144 break;
145  
146  
147 // Decide which address to lease out
148 // Note that this needs to be changed if we are to
149 // support more than one lease
150 DHCPNextLease.Val = (AppConfig.MyIPAddr.Val & AppConfig.MyMask.Val) + 0x02000000;
151 if(DHCPNextLease.v[3] == 255u)
152 DHCPNextLease.v[3] += 0x03;
153 if(DHCPNextLease.v[3] == 0u)
154 DHCPNextLease.v[3] += 0x02;
155  
156 smDHCPServer++;
157  
158 case DHCP_LISTEN:
159 // Check to see if a valid DHCP packet has arrived
160 if(UDPIsGetReady(MySocket) < 241u)
161 break;
162  
163 // Retrieve the BOOTP header
164 UDPGetArray((BYTE*)&BOOTPHeader, sizeof(BOOTPHeader));
165  
166 bAccept = (BOOTPHeader.ClientIP.Val == DHCPNextLease.Val) || (BOOTPHeader.ClientIP.Val == 0x00000000u);
167  
168 // Validate first three fields
169 if(BOOTPHeader.MessageType != 1u)
170 break;
171 if(BOOTPHeader.HardwareType != 1u)
172 break;
173 if(BOOTPHeader.HardwareLen != 6u)
174 break;
175  
176 // Throw away 10 unused bytes of hardware address,
177 // server host name, and boot file name -- unsupported/not needed.
178 for(i = 0; i < 64+128+(16-sizeof(MAC_ADDR)); i++)
179 UDPGet(&Option);
180  
181 // Obtain Magic Cookie and verify
182 UDPGetArray((BYTE*)&dw, sizeof(DWORD));
183 if(dw != 0x63538263ul)
184 break;
185  
186 // Obtain options
187 while(1)
188 {
189 // Get option type
190 if(!UDPGet(&Option))
191 break;
192 if(Option == DHCP_END_OPTION)
193 break;
194  
195 // Get option length
196 UDPGet(&Len);
197  
198 // Process option
199 switch(Option)
200 {
201 case DHCP_MESSAGE_TYPE:
202 UDPGet(&i);
203 switch(i)
204 {
205 case DHCP_DISCOVER_MESSAGE:
206 DHCPReplyToDiscovery(&BOOTPHeader);
207 break;
208  
209 case DHCP_REQUEST_MESSAGE:
210 #if defined(STACK_USE_ZEROCONF_LINK_LOCAL)
211 if ( (BOOTPHeader.ClientIP.Val == 0x00000000u) &&
212 (bLeaseAvailable == FALSE) )
213 {
214 // Lease available only to the current lease holder
215 break;
216 }
217 #endif
218  
219 DHCPReplyToRequest(&BOOTPHeader, bAccept);
220  
221 #if defined(STACK_USE_ZEROCONF_LINK_LOCAL)
222 bLeaseAvailable = FALSE;
223 #endif
224  
225 break;
226  
227 // Need to handle these if supporting more than one DHCP lease
228 case DHCP_RELEASE_MESSAGE:
229 case DHCP_DECLINE_MESSAGE:
230 break;
231 }
232 break;
233  
234 case DHCP_PARAM_REQUEST_IP_ADDRESS:
235 if(Len == 4u)
236 {
237 // Get the requested IP address and see if it is the one we have on offer.
238 UDPGetArray((BYTE*)&dw, 4);
239 Len -= 4;
240 bAccept = (dw == DHCPNextLease.Val);
241 }
242 break;
243  
244 case DHCP_END_OPTION:
245 UDPDiscard();
246 return;
247 }
248  
249 // Remove any unprocessed bytes that we don't care about
250 while(Len--)
251 {
252 UDPGet(&i);
253 }
254 }
255  
256 UDPDiscard();
257 break;
258 }
259 }
260  
261  
262 /*****************************************************************************
263 Function:
264 static void DHCPReplyToDiscovery(BOOTP_HEADER *Header)
265  
266 Summary:
267 Replies to a DHCP Discover message.
268  
269 Description:
270 This function replies to a DHCP Discover message by sending out a
271 DHCP Offer message.
272  
273 Precondition:
274 None
275  
276 Parameters:
277 Header - the BootP header this is in response to.
278  
279 Returns:
280 None
281 ***************************************************************************/
282 static void DHCPReplyToDiscovery(BOOTP_HEADER *Header)
283 {
284 BYTE i;
285  
286 // Set the correct socket to active and ensure that
287 // enough space is available to generate the DHCP response
288 if(UDPIsPutReady(MySocket) < 300u)
289 return;
290  
291 // Begin putting the BOOTP Header and DHCP options
292 UDPPut(BOOT_REPLY); // Message Type: 2 (BOOTP Reply)
293 // Reply with the same Hardware Type, Hardware Address Length, Hops, and Transaction ID fields
294 UDPPutArray((BYTE*)&(Header->HardwareType), 7);
295 UDPPut(0x00); // Seconds Elapsed: 0 (Not used)
296 UDPPut(0x00); // Seconds Elapsed: 0 (Not used)
297 UDPPutArray((BYTE*)&(Header->BootpFlags), sizeof(Header->BootpFlags));
298 UDPPut(0x00); // Your (client) IP Address: 0.0.0.0 (none yet assigned)
299 UDPPut(0x00); // Your (client) IP Address: 0.0.0.0 (none yet assigned)
300 UDPPut(0x00); // Your (client) IP Address: 0.0.0.0 (none yet assigned)
301 UDPPut(0x00); // Your (client) IP Address: 0.0.0.0 (none yet assigned)
302 UDPPutArray((BYTE*)&DHCPNextLease, sizeof(IP_ADDR)); // Lease IP address to give out
303 UDPPut(0x00); // Next Server IP Address: 0.0.0.0 (not used)
304 UDPPut(0x00); // Next Server IP Address: 0.0.0.0 (not used)
305 UDPPut(0x00); // Next Server IP Address: 0.0.0.0 (not used)
306 UDPPut(0x00); // Next Server IP Address: 0.0.0.0 (not used)
307 UDPPut(0x00); // Relay Agent IP Address: 0.0.0.0 (not used)
308 UDPPut(0x00); // Relay Agent IP Address: 0.0.0.0 (not used)
309 UDPPut(0x00); // Relay Agent IP Address: 0.0.0.0 (not used)
310 UDPPut(0x00); // Relay Agent IP Address: 0.0.0.0 (not used)
311 UDPPutArray((BYTE*)&(Header->ClientMAC), sizeof(MAC_ADDR)); // Client MAC address: Same as given by client
312 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)
313 UDPPut(0x00); // Boot filename: Null string (not used)
314 UDPPut(0x63); // Magic Cookie: 0x63538263
315 UDPPut(0x82); // Magic Cookie: 0x63538263
316 UDPPut(0x53); // Magic Cookie: 0x63538263
317 UDPPut(0x63); // Magic Cookie: 0x63538263
318  
319 // Options: DHCP Offer
320 UDPPut(DHCP_MESSAGE_TYPE);
321 UDPPut(1);
322 UDPPut(DHCP_OFFER_MESSAGE);
323  
324 // Option: Subnet Mask
325 UDPPut(DHCP_SUBNET_MASK);
326 UDPPut(sizeof(IP_ADDR));
327 UDPPutArray((BYTE*)&AppConfig.MyMask, sizeof(IP_ADDR));
328  
329 // Option: Lease duration
330 UDPPut(DHCP_IP_LEASE_TIME);
331 UDPPut(4);
332 UDPPut((DHCP_LEASE_DURATION>>24) & 0xFF);
333 UDPPut((DHCP_LEASE_DURATION>>16) & 0xFF);
334 UDPPut((DHCP_LEASE_DURATION>>8) & 0xFF);
335 UDPPut((DHCP_LEASE_DURATION) & 0xFF);
336  
337 // Option: Server identifier
338 UDPPut(DHCP_SERVER_IDENTIFIER);
339 UDPPut(sizeof(IP_ADDR));
340 UDPPutArray((BYTE*)&AppConfig.MyIPAddr, sizeof(IP_ADDR));
341  
342 // Option: Router/Gateway address
343 UDPPut(DHCP_ROUTER);
344 UDPPut(sizeof(IP_ADDR));
345 UDPPutArray((BYTE*)&AppConfig.MyIPAddr, sizeof(IP_ADDR));
346  
347 // Option: DNS server address
348 UDPPut(DHCP_DNS);
349 UDPPut(sizeof(IP_ADDR));
350 UDPPutArray((BYTE*)&AppConfig.MyIPAddr, sizeof(IP_ADDR));
351  
352 // No more options, mark ending
353 UDPPut(DHCP_END_OPTION);
354  
355 // Add zero padding to ensure compatibility with old BOOTP relays that discard small packets (<300 UDP octets)
356 while(UDPTxCount < 300u)
357 UDPPut(0);
358  
359 // Force remote destination address to be the broadcast address, regardless
360 // of what the node's source IP address was (to ensure we don't try to
361 // unicast to 0.0.0.0).
362 memset((void*)&UDPSocketInfo[MySocket].remoteNode, 0xFF, sizeof(NODE_INFO));
363  
364 // Transmit the packet
365 UDPFlush();
366 }
367  
368  
369 /*****************************************************************************
370 Function:
371 static void DHCPReplyToRequest(BOOTP_HEADER *Header, BOOL bAccept)
372  
373 Summary:
374 Replies to a DHCP Request message.
375  
376 Description:
377 This function replies to a DHCP Request message by sending out a
378 DHCP Acknowledge message.
379  
380 Precondition:
381 None
382  
383 Parameters:
384 Header - the BootP header this is in response to.
385 bAccept - whether or not we've accepted this request
386  
387 Returns:
388 None
389  
390 Internal:
391 Needs to support more than one simultaneous lease in the future.
392 ***************************************************************************/
393 static void DHCPReplyToRequest(BOOTP_HEADER *Header, BOOL bAccept)
394 {
395 BYTE i;
396  
397 // Set the correct socket to active and ensure that
398 // enough space is available to generate the DHCP response
399 if(UDPIsPutReady(MySocket) < 300u)
400 return;
401  
402 // Search through all remaining options and look for the Requested IP address field
403 // Obtain options
404 while(UDPIsGetReady(MySocket))
405 {
406 BYTE Option, Len;
407 DWORD dw;
408  
409 // Get option type
410 if(!UDPGet(&Option))
411 break;
412 if(Option == DHCP_END_OPTION)
413 break;
414  
415 // Get option length
416 UDPGet(&Len);
417  
418 // Process option
419 if((Option == DHCP_PARAM_REQUEST_IP_ADDRESS) && (Len == 4u))
420 {
421 // 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.
422 UDPGetArray((BYTE*)&dw, 4);
423 Len -= 4;
424 if(dw != DHCPNextLease.Val)
425 {
426 bAccept = FALSE;
427 }
428 break;
429 }
430  
431 // Remove the unprocessed bytes that we don't care about
432 while(Len--)
433 {
434 UDPGet(&i);
435 }
436 }
437  
438 // Begin putting the BOOTP Header and DHCP options
439 UDPPut(BOOT_REPLY); // Message Type: 2 (BOOTP Reply)
440 // Reply with the same Hardware Type, Hardware Address Length, Hops, and Transaction ID fields
441 UDPPutArray((BYTE*)&(Header->HardwareType), 7);
442 UDPPut(0x00); // Seconds Elapsed: 0 (Not used)
443 UDPPut(0x00); // Seconds Elapsed: 0 (Not used)
444 UDPPutArray((BYTE*)&(Header->BootpFlags), sizeof(Header->BootpFlags));
445 UDPPutArray((BYTE*)&(Header->ClientIP), sizeof(IP_ADDR));// Your (client) IP Address:
446 UDPPutArray((BYTE*)&DHCPNextLease, sizeof(IP_ADDR)); // Lease IP address to give out
447 UDPPut(0x00); // Next Server IP Address: 0.0.0.0 (not used)
448 UDPPut(0x00); // Next Server IP Address: 0.0.0.0 (not used)
449 UDPPut(0x00); // Next Server IP Address: 0.0.0.0 (not used)
450 UDPPut(0x00); // Next Server IP Address: 0.0.0.0 (not used)
451 UDPPut(0x00); // Relay Agent IP Address: 0.0.0.0 (not used)
452 UDPPut(0x00); // Relay Agent IP Address: 0.0.0.0 (not used)
453 UDPPut(0x00); // Relay Agent IP Address: 0.0.0.0 (not used)
454 UDPPut(0x00); // Relay Agent IP Address: 0.0.0.0 (not used)
455 UDPPutArray((BYTE*)&(Header->ClientMAC), sizeof(MAC_ADDR)); // Client MAC address: Same as given by client
456 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)
457 UDPPut(0x00); // Boot filename: Null string (not used)
458 UDPPut(0x63); // Magic Cookie: 0x63538263
459 UDPPut(0x82); // Magic Cookie: 0x63538263
460 UDPPut(0x53); // Magic Cookie: 0x63538263
461 UDPPut(0x63); // Magic Cookie: 0x63538263
462  
463 // Options: DHCP lease ACKnowledge
464 if(bAccept)
465 {
466 UDPPut(DHCP_OPTION_ACK_MESSAGE);
467 UDPPut(1);
468 UDPPut(DHCP_ACK_MESSAGE);
469 }
470 else // Send a NACK
471 {
472 UDPPut(DHCP_OPTION_ACK_MESSAGE);
473 UDPPut(1);
474 UDPPut(DHCP_NAK_MESSAGE);
475 }
476  
477 // Option: Lease duration
478 UDPPut(DHCP_IP_LEASE_TIME);
479 UDPPut(4);
480 UDPPut((DHCP_LEASE_DURATION>>24) & 0xFF);
481 UDPPut((DHCP_LEASE_DURATION>>16) & 0xFF);
482 UDPPut((DHCP_LEASE_DURATION>>8) & 0xFF);
483 UDPPut((DHCP_LEASE_DURATION) & 0xFF);
484  
485 // Option: Server identifier
486 UDPPut(DHCP_SERVER_IDENTIFIER);
487 UDPPut(sizeof(IP_ADDR));
488 UDPPutArray((BYTE*)&AppConfig.MyIPAddr, sizeof(IP_ADDR));
489  
490 // Option: Subnet Mask
491 UDPPut(DHCP_SUBNET_MASK);
492 UDPPut(sizeof(IP_ADDR));
493 UDPPutArray((BYTE*)&AppConfig.MyMask, sizeof(IP_ADDR));
494  
495 // Option: Router/Gateway address
496 UDPPut(DHCP_ROUTER);
497 UDPPut(sizeof(IP_ADDR));
498 UDPPutArray((BYTE*)&AppConfig.MyIPAddr, sizeof(IP_ADDR));
499  
500 // Option: DNS server address
501 UDPPut(DHCP_DNS);
502 UDPPut(sizeof(IP_ADDR));
503 UDPPutArray((BYTE*)&AppConfig.MyIPAddr, sizeof(IP_ADDR));
504  
505 // No more options, mark ending
506 UDPPut(DHCP_END_OPTION);
507  
508 // Add zero padding to ensure compatibility with old BOOTP relays that discard small packets (<300 UDP octets)
509 while(UDPTxCount < 300u)
510 UDPPut(0);
511  
512 // Force remote destination address to be the broadcast address, regardless
513 // of what the node's source IP address was (to ensure we don't try to
514 // unicast to 0.0.0.0).
515 memset((void*)&UDPSocketInfo[MySocket].remoteNode, 0xFF, sizeof(NODE_INFO));
516  
517 // Transmit the packet
518 UDPFlush();
519 }
520  
521 #endif //#if defined(STACK_USE_DHCP_SERVER)
{BLAME END}
{FOOTER START}

Powered by WebSVN v2.8.3