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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 15 - (hide annotations) (download)
Thu Apr 19 09:01:15 2007 UTC (17 years, 2 months ago) by hedin
File MIME type: text/plain
File size: 14138 byte(s)
added the TCP/IP stack, source code.
1 hedin 15 /*********************************************************************
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