source: ctrl/firmware/Main/SES/Wiznet/Internet/DHCP/dhcp.c

Last change on this file was 79, checked in by Zed, 3 months ago

DHCP client can get IP-address from fritz!box

File size: 29.6 KB
Line 
1//*****************************************************************************
2//
3//! \file dhcp.c
4//! \brief DHCP APIs implement file.
5//! \details Processing DHCP protocol as DISCOVER, OFFER, REQUEST, ACK, NACK and DECLINE.
6//! \version 1.1.1
7//! \date 2019/10/08
8//! \par  Revision history
9//!       <2019/10/08> compare DHCP server ip address
10//!       <2013/11/18> 1st Release
11//!       <2012/12/20> V1.1.0
12//!         1. Optimize code
13//!         2. Add reg_dhcp_cbfunc()
14//!         3. Add DHCP_stop()
15//!         4. Integrate check_DHCP_state() & DHCP_run() to DHCP_run()
16//!         5. Don't care system endian
17//!         6. Add comments
18//!       <2012/12/26> V1.1.1
19//!         1. Modify variable declaration: dhcp_tick_1s is declared volatile for code optimization
20//! \author Eric Jung & MidnightCow
21//! \copyright
22//!
23//! Copyright (c)  2013, WIZnet Co., LTD.
24//! All rights reserved.
25//!
26//! Redistribution and use in source and binary forms, with or without
27//! modification, are permitted provided that the following conditions
28//! are met:
29//!
30//!     * Redistributions of source code must retain the above copyright
31//! notice, this list of conditions and the following disclaimer.
32//!     * Redistributions in binary form must reproduce the above copyright
33//! notice, this list of conditions and the following disclaimer in the
34//! documentation and/or other materials provided with the distribution.
35//!     * Neither the name of the <ORGANIZATION> nor the names of its
36//! contributors may be used to endorse or promote products derived
37//! from this software without specific prior written permission.
38//!
39//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
40//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
42//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
43//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
44//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
45//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
46//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
47//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
49//! THE POSSIBILITY OF SUCH DAMAGE.
50//
51//*****************************************************************************
52
53#include "socket.h"
54#include "dhcp.h"
55
56/* If you want to display debug & processing message, Define _DHCP_DEBUG_ in dhcp.h */
57
58#ifdef _DHCP_DEBUG_
59   #include <stdio.h>
60#endif
61
62/* DHCP state machine. */
63#define STATE_DHCP_INIT          0        ///< Initialize
64#define STATE_DHCP_DISCOVER      1        ///< send DISCOVER and wait OFFER
65#define STATE_DHCP_REQUEST       2        ///< send REQEUST and wait ACK or NACK
66#define STATE_DHCP_LEASED        3        ///< ReceiveD ACK and IP leased
67#define STATE_DHCP_REREQUEST     4        ///< send REQUEST for maintaining leased IP
68#define STATE_DHCP_RELEASE       5        ///< No use
69#define STATE_DHCP_STOP          6        ///< Stop processing DHCP
70
71#define DHCP_FLAGSBROADCAST      0x8000   ///< The broadcast value of flags in @ref RIP_MSG
72#define DHCP_FLAGSUNICAST        0x0000   ///< The unicast   value of flags in @ref RIP_MSG
73
74/* DHCP message OP code */
75#define DHCP_BOOTREQUEST         1        ///< Request Message used in op of @ref RIP_MSG
76#define DHCP_BOOTREPLY           2        ///< Reply Message used i op of @ref RIP_MSG
77
78/* DHCP message type */
79#define DHCP_DISCOVER            1        ///< DISCOVER message in OPT of @ref RIP_MSG
80#define DHCP_OFFER               2        ///< OFFER message in OPT of @ref RIP_MSG
81#define DHCP_REQUEST             3        ///< REQUEST message in OPT of @ref RIP_MSG
82#define DHCP_DECLINE             4        ///< DECLINE message in OPT of @ref RIP_MSG
83#define DHCP_ACK                 5        ///< ACK message in OPT of @ref RIP_MSG
84#define DHCP_NAK                 6        ///< NACK message in OPT of @ref RIP_MSG
85#define DHCP_RELEASE             7        ///< RELEASE message in OPT of @ref RIP_MSG. No use
86#define DHCP_INFORM              8        ///< INFORM message in OPT of @ref RIP_MSG. No use
87
88#define DHCP_HTYPE10MB           1        ///< Used in type of @ref RIP_MSG
89#define DHCP_HTYPE100MB          2        ///< Used in type of @ref RIP_MSG
90
91#define DHCP_HLENETHERNET        6        ///< Used in hlen of @ref RIP_MSG
92#define DHCP_HOPS                0        ///< Used in hops of @ref RIP_MSG
93#define DHCP_SECS                0        ///< Used in secs of @ref RIP_MSG
94
95#define INFINITE_LEASETIME       0xffffffff     ///< Infinite lease time
96
97#define OPT_SIZE                 312               /// Max OPT size of @ref RIP_MSG
98#define RIP_MSG_SIZE             (236+OPT_SIZE)    /// Max size of @ref RIP_MSG
99
100/*
101 * @brief DHCP option and value (cf. RFC1533)
102 */
103enum
104{
105   padOption               = 0,
106   subnetMask              = 1,
107   timerOffset             = 2,
108   routersOnSubnet         = 3,
109   timeServer              = 4,
110   nameServer              = 5,
111   dns                     = 6,
112   logServer               = 7,
113   cookieServer            = 8,
114   lprServer               = 9,
115   impressServer           = 10,
116   resourceLocationServer       = 11,
117   hostName                = 12,
118   bootFileSize            = 13,
119   meritDumpFile           = 14,
120   domainName              = 15,
121   swapServer              = 16,
122   rootPath                = 17,
123   extentionsPath          = 18,
124   IPforwarding            = 19,
125   nonLocalSourceRouting   = 20,
126   policyFilter            = 21,
127   maxDgramReasmSize       = 22,
128   defaultIPTTL            = 23,
129   pathMTUagingTimeout     = 24,
130   pathMTUplateauTable     = 25,
131   ifMTU                   = 26,
132   allSubnetsLocal         = 27,
133   broadcastAddr           = 28,
134   performMaskDiscovery    = 29,
135   maskSupplier            = 30,
136   performRouterDiscovery  = 31,
137   routerSolicitationAddr  = 32,
138   staticRoute             = 33,
139   trailerEncapsulation    = 34,
140   arpCacheTimeout         = 35,
141   ethernetEncapsulation   = 36,
142   tcpDefaultTTL           = 37,
143   tcpKeepaliveInterval    = 38,
144   tcpKeepaliveGarbage     = 39,
145   nisDomainName           = 40,
146   nisServers              = 41,
147   ntpServers              = 42,
148   vendorSpecificInfo      = 43,
149   netBIOSnameServer       = 44,
150   netBIOSdgramDistServer       = 45,
151   netBIOSnodeType         = 46,
152   netBIOSscope            = 47,
153   xFontServer             = 48,
154   xDisplayManager         = 49,
155   dhcpRequestedIPaddr     = 50,
156   dhcpIPaddrLeaseTime     = 51,
157   dhcpOptionOverload      = 52,
158   dhcpMessageType         = 53,
159   dhcpServerIdentifier    = 54,
160   dhcpParamRequest        = 55,
161   dhcpMsg                 = 56,
162   dhcpMaxMsgSize          = 57,
163   dhcpT1value             = 58,
164   dhcpT2value             = 59,
165   dhcpClassIdentifier     = 60,
166   dhcpClientIdentifier    = 61,
167   endOption               = 255
168};
169
170/*
171 * @brief DHCP message format
172 */
173typedef struct {
174        uint8_t  op;            ///< @ref DHCP_BOOTREQUEST or @ref DHCP_BOOTREPLY
175        uint8_t  htype;         ///< @ref DHCP_HTYPE10MB or @ref DHCP_HTYPE100MB
176        uint8_t  hlen;          ///< @ref DHCP_HLENETHERNET
177        uint8_t  hops;          ///< @ref DHCP_HOPS
178        uint32_t xid;           ///< @ref DHCP_XID  This increase one every DHCP transaction.
179        uint16_t secs;          ///< @ref DHCP_SECS
180        uint16_t flags;         ///< @ref DHCP_FLAGSBROADCAST or @ref DHCP_FLAGSUNICAST
181        uint8_t  ciaddr[4];     ///< @ref Request IP to DHCP sever
182        uint8_t  yiaddr[4];     ///< @ref Offered IP from DHCP server
183        uint8_t  siaddr[4];     ///< No use
184        uint8_t  giaddr[4];     ///< No use
185        uint8_t  chaddr[16];    ///< DHCP client 6bytes MAC address. Others is filled to zero
186        uint8_t  sname[64];     ///< No use
187        uint8_t  file[128];     ///< No use
188        uint8_t  OPT[OPT_SIZE]; ///< Option
189} RIP_MSG;
190
191
192
193uint8_t DHCP_SOCKET;                      // Socket number for DHCP
194
195uint8_t DHCP_SIP[4];                      // DHCP Server IP address
196uint8_t DHCP_REAL_SIP[4];                 // For extract my DHCP server in a few DHCP server
197
198// Network information from DHCP Server
199uint8_t OLD_allocated_ip[4]   = {0, };    // Previous IP address
200uint8_t DHCP_allocated_ip[4]  = {0, };    // IP address from DHCP
201uint8_t DHCP_allocated_gw[4]  = {0, };    // Gateway address from DHCP
202uint8_t DHCP_allocated_sn[4]  = {0, };    // Subnet mask from DHCP
203uint8_t DHCP_allocated_dns[4] = {0, };    // DNS address from DHCP
204
205
206int8_t   dhcp_state        = STATE_DHCP_INIT;   // DHCP state
207int8_t   dhcp_retry_count  = 0;
208
209uint32_t dhcp_lease_time                        = INFINITE_LEASETIME;
210volatile uint32_t dhcp_tick_1s      = 0;                 // unit 1 second
211uint32_t dhcp_tick_next                         = DHCP_WAIT_TIME ;
212
213uint32_t DHCP_XID;      // Any number
214
215RIP_MSG* pDHCPMSG;      // Buffer pointer for DHCP processing
216
217uint8_t HOST_NAME[] = DCHP_HOST_NAME;
218
219uint8_t DHCP_CHADDR[6]; // DHCP Client MAC address.
220
221/* The default callback function */
222void default_ip_assign(void);
223void default_ip_update(void);
224void default_ip_conflict(void);
225
226/* Callback handler */
227void (*dhcp_ip_assign)(void)   = default_ip_assign;     /* handler to be called when the IP address from DHCP server is first assigned */
228void (*dhcp_ip_update)(void)   = default_ip_update;     /* handler to be called when the IP address from DHCP server is updated */
229void (*dhcp_ip_conflict)(void) = default_ip_conflict;   /* handler to be called when the IP address from DHCP server is conflict */
230
231void reg_dhcp_cbfunc(void(*ip_assign)(void), void(*ip_update)(void), void(*ip_conflict)(void));
232
233char NibbleToHex(uint8_t nibble);
234
235/* send DISCOVER message to DHCP server */
236void     send_DHCP_DISCOVER(void);
237
238/* send REQEUST message to DHCP server */
239void     send_DHCP_REQUEST(void);
240
241/* send DECLINE message to DHCP server */
242void     send_DHCP_DECLINE(void);
243
244/* IP conflict check by sending ARP-request to leased IP and wait ARP-response. */
245int8_t   check_DHCP_leasedIP(void);
246
247/* check the timeout in DHCP process */
248uint8_t  check_DHCP_timeout(void);
249
250/* Initialize to timeout process.  */
251void     reset_DHCP_timeout(void);
252
253/* Parse message as OFFER and ACK and NACK from DHCP server.*/
254int8_t   parseDHCPCMSG(void);
255
256/* The default handler of ip assign first */
257void default_ip_assign(void)
258{
259   setSIPR(DHCP_allocated_ip);
260   setSUBR(DHCP_allocated_sn);
261   setGAR (DHCP_allocated_gw);
262}
263
264/* The default handler of ip changed */
265void default_ip_update(void)
266{
267        /* WIZchip Software Reset */
268   setMR(MR_RST);
269   getMR(); // for delay
270   default_ip_assign();
271   setSHAR(DHCP_CHADDR);
272}
273
274/* The default handler of ip changed */
275void default_ip_conflict(void)
276{
277        // WIZchip Software Reset
278        setMR(MR_RST);
279        getMR(); // for delay
280        setSHAR(DHCP_CHADDR);
281}
282
283/* register the call back func. */
284void reg_dhcp_cbfunc(void(*ip_assign)(void), void(*ip_update)(void), void(*ip_conflict)(void))
285{
286   dhcp_ip_assign   = default_ip_assign;
287   dhcp_ip_update   = default_ip_update;
288   dhcp_ip_conflict = default_ip_conflict;
289   if(ip_assign)   dhcp_ip_assign = ip_assign;
290   if(ip_update)   dhcp_ip_update = ip_update;
291   if(ip_conflict) dhcp_ip_conflict = ip_conflict;
292}
293
294/* make the common DHCP message */
295void makeDHCPMSG(void)
296{
297   uint8_t  bk_mac[6];
298   uint8_t* ptmp;
299   uint8_t  i;
300   getSHAR(bk_mac);
301        pDHCPMSG->op      = DHCP_BOOTREQUEST;
302        pDHCPMSG->htype   = DHCP_HTYPE10MB;
303        pDHCPMSG->hlen    = DHCP_HLENETHERNET;
304        pDHCPMSG->hops    = DHCP_HOPS;
305        ptmp              = (uint8_t*)(&pDHCPMSG->xid);
306        *(ptmp+0)         = (uint8_t)((DHCP_XID & 0xFF000000) >> 24);
307        *(ptmp+1)         = (uint8_t)((DHCP_XID & 0x00FF0000) >> 16);
308   *(ptmp+2)         = (uint8_t)((DHCP_XID & 0x0000FF00) >>  8);
309        *(ptmp+3)         = (uint8_t)((DHCP_XID & 0x000000FF) >>  0);
310        pDHCPMSG->secs    = DHCP_SECS;
311        ptmp              = (uint8_t*)(&pDHCPMSG->flags);
312        *(ptmp+0)         = (uint8_t)((DHCP_FLAGSBROADCAST & 0xFF00) >> 8);
313        *(ptmp+1)         = (uint8_t)((DHCP_FLAGSBROADCAST & 0x00FF) >> 0);
314
315        pDHCPMSG->ciaddr[0] = 0;
316        pDHCPMSG->ciaddr[1] = 0;
317        pDHCPMSG->ciaddr[2] = 0;
318        pDHCPMSG->ciaddr[3] = 0;
319
320        pDHCPMSG->yiaddr[0] = 0;
321        pDHCPMSG->yiaddr[1] = 0;
322        pDHCPMSG->yiaddr[2] = 0;
323        pDHCPMSG->yiaddr[3] = 0;
324
325        pDHCPMSG->siaddr[0] = 0;
326        pDHCPMSG->siaddr[1] = 0;
327        pDHCPMSG->siaddr[2] = 0;
328        pDHCPMSG->siaddr[3] = 0;
329
330        pDHCPMSG->giaddr[0] = 0;
331        pDHCPMSG->giaddr[1] = 0;
332        pDHCPMSG->giaddr[2] = 0;
333        pDHCPMSG->giaddr[3] = 0;
334
335        pDHCPMSG->chaddr[0] = DHCP_CHADDR[0];
336        pDHCPMSG->chaddr[1] = DHCP_CHADDR[1];
337        pDHCPMSG->chaddr[2] = DHCP_CHADDR[2];
338        pDHCPMSG->chaddr[3] = DHCP_CHADDR[3];
339        pDHCPMSG->chaddr[4] = DHCP_CHADDR[4];
340        pDHCPMSG->chaddr[5] = DHCP_CHADDR[5];
341
342        for (i = 6; i < 16; i++)  pDHCPMSG->chaddr[i] = 0;
343        for (i = 0; i < 64; i++)  pDHCPMSG->sname[i]  = 0;
344        for (i = 0; i < 128; i++) pDHCPMSG->file[i]   = 0;
345
346        // MAGIC_COOKIE
347        pDHCPMSG->OPT[0] = (uint8_t)((MAGIC_COOKIE & 0xFF000000) >> 24);
348        pDHCPMSG->OPT[1] = (uint8_t)((MAGIC_COOKIE & 0x00FF0000) >> 16);
349        pDHCPMSG->OPT[2] = (uint8_t)((MAGIC_COOKIE & 0x0000FF00) >>  8);
350        pDHCPMSG->OPT[3] = (uint8_t) (MAGIC_COOKIE & 0x000000FF) >>  0;
351}
352
353/* SEND DHCP DISCOVER */
354void send_DHCP_DISCOVER(void)
355{
356        uint16_t i;
357        uint8_t ip[4];
358        uint16_t k = 0;
359
360   makeDHCPMSG();
361   DHCP_SIP[0]=0;
362   DHCP_SIP[1]=0;
363   DHCP_SIP[2]=0;
364   DHCP_SIP[3]=0;
365   DHCP_REAL_SIP[0]=0;
366   DHCP_REAL_SIP[1]=0;
367   DHCP_REAL_SIP[2]=0;
368   DHCP_REAL_SIP[3]=0;
369
370   k = 4;     // because MAGIC_COOKIE already made by makeDHCPMSG()
371
372        // Option Request Param
373        pDHCPMSG->OPT[k++] = dhcpMessageType;
374        pDHCPMSG->OPT[k++] = 0x01;
375        pDHCPMSG->OPT[k++] = DHCP_DISCOVER;
376
377        // Client identifier
378        pDHCPMSG->OPT[k++] = dhcpClientIdentifier;
379        pDHCPMSG->OPT[k++] = 0x07;
380        pDHCPMSG->OPT[k++] = 0x01;
381        pDHCPMSG->OPT[k++] = DHCP_CHADDR[0];
382        pDHCPMSG->OPT[k++] = DHCP_CHADDR[1];
383        pDHCPMSG->OPT[k++] = DHCP_CHADDR[2];
384        pDHCPMSG->OPT[k++] = DHCP_CHADDR[3];
385        pDHCPMSG->OPT[k++] = DHCP_CHADDR[4];
386        pDHCPMSG->OPT[k++] = DHCP_CHADDR[5];
387
388        // host name
389        pDHCPMSG->OPT[k++] = hostName;
390        pDHCPMSG->OPT[k++] = 0;          // fill zero length of hostname
391        for(i = 0 ; HOST_NAME[i] != 0; i++)
392        pDHCPMSG->OPT[k++] = HOST_NAME[i];
393        pDHCPMSG->OPT[k++] = NibbleToHex(DHCP_CHADDR[3] >> 4);
394        pDHCPMSG->OPT[k++] = NibbleToHex(DHCP_CHADDR[3]);
395        pDHCPMSG->OPT[k++] = NibbleToHex(DHCP_CHADDR[4] >> 4);
396        pDHCPMSG->OPT[k++] = NibbleToHex(DHCP_CHADDR[4]);
397        pDHCPMSG->OPT[k++] = NibbleToHex(DHCP_CHADDR[5] >> 4);
398        pDHCPMSG->OPT[k++] = NibbleToHex(DHCP_CHADDR[5]);
399        pDHCPMSG->OPT[k - (i+6+1)] = i+6; // length of hostname
400
401        pDHCPMSG->OPT[k++] = dhcpParamRequest;
402        pDHCPMSG->OPT[k++] = 0x06;      // length of request
403        pDHCPMSG->OPT[k++] = subnetMask;
404        pDHCPMSG->OPT[k++] = routersOnSubnet;
405        pDHCPMSG->OPT[k++] = dns;
406        pDHCPMSG->OPT[k++] = domainName;
407        pDHCPMSG->OPT[k++] = dhcpT1value;
408        pDHCPMSG->OPT[k++] = dhcpT2value;
409        pDHCPMSG->OPT[k++] = endOption;
410
411        for (i = k; i < OPT_SIZE; i++) pDHCPMSG->OPT[i] = 0;
412
413        // send broadcasting packet
414        ip[0] = 255;
415        ip[1] = 255;
416        ip[2] = 255;
417        ip[3] = 255;
418
419#ifdef _DHCP_DEBUG_
420        printf("> Send DHCP_DISCOVER\r\n");
421#endif
422
423        sendto(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT);
424}
425
426/* SEND DHCP REQUEST */
427void send_DHCP_REQUEST(void)
428{
429        int i;
430        uint8_t ip[4];
431        uint16_t k = 0;
432
433   makeDHCPMSG();
434
435   if(dhcp_state == STATE_DHCP_LEASED || dhcp_state == STATE_DHCP_REREQUEST)
436   {
437        *((uint8_t*)(&pDHCPMSG->flags))   = ((DHCP_FLAGSUNICAST & 0xFF00)>> 8);
438        *((uint8_t*)(&pDHCPMSG->flags)+1) = (DHCP_FLAGSUNICAST & 0x00FF);
439        pDHCPMSG->ciaddr[0] = DHCP_allocated_ip[0];
440        pDHCPMSG->ciaddr[1] = DHCP_allocated_ip[1];
441        pDHCPMSG->ciaddr[2] = DHCP_allocated_ip[2];
442        pDHCPMSG->ciaddr[3] = DHCP_allocated_ip[3];
443        ip[0] = DHCP_SIP[0];
444        ip[1] = DHCP_SIP[1];
445        ip[2] = DHCP_SIP[2];
446        ip[3] = DHCP_SIP[3];
447   }
448   else
449   {
450        ip[0] = 255;
451        ip[1] = 255;
452        ip[2] = 255;
453        ip[3] = 255;
454   }
455
456   k = 4;      // because MAGIC_COOKIE already made by makeDHCPMSG()
457
458        // Option Request Param.
459        pDHCPMSG->OPT[k++] = dhcpMessageType;
460        pDHCPMSG->OPT[k++] = 0x01;
461        pDHCPMSG->OPT[k++] = DHCP_REQUEST;
462
463        pDHCPMSG->OPT[k++] = dhcpClientIdentifier;
464        pDHCPMSG->OPT[k++] = 0x07;
465        pDHCPMSG->OPT[k++] = 0x01;
466        pDHCPMSG->OPT[k++] = DHCP_CHADDR[0];
467        pDHCPMSG->OPT[k++] = DHCP_CHADDR[1];
468        pDHCPMSG->OPT[k++] = DHCP_CHADDR[2];
469        pDHCPMSG->OPT[k++] = DHCP_CHADDR[3];
470        pDHCPMSG->OPT[k++] = DHCP_CHADDR[4];
471        pDHCPMSG->OPT[k++] = DHCP_CHADDR[5];
472
473   if(ip[3] == 255)  // if(dchp_state == STATE_DHCP_LEASED || dchp_state == DHCP_REREQUEST_STATE)
474   {
475                pDHCPMSG->OPT[k++] = dhcpRequestedIPaddr;
476                pDHCPMSG->OPT[k++] = 0x04;
477                pDHCPMSG->OPT[k++] = DHCP_allocated_ip[0];
478                pDHCPMSG->OPT[k++] = DHCP_allocated_ip[1];
479                pDHCPMSG->OPT[k++] = DHCP_allocated_ip[2];
480                pDHCPMSG->OPT[k++] = DHCP_allocated_ip[3];
481
482                pDHCPMSG->OPT[k++] = dhcpServerIdentifier;
483                pDHCPMSG->OPT[k++] = 0x04;
484                pDHCPMSG->OPT[k++] = DHCP_SIP[0];
485                pDHCPMSG->OPT[k++] = DHCP_SIP[1];
486                pDHCPMSG->OPT[k++] = DHCP_SIP[2];
487                pDHCPMSG->OPT[k++] = DHCP_SIP[3];
488        }
489
490        // host name
491        pDHCPMSG->OPT[k++] = hostName;
492        pDHCPMSG->OPT[k++] = 0; // length of hostname
493        for(i = 0 ; HOST_NAME[i] != 0; i++)
494        pDHCPMSG->OPT[k++] = HOST_NAME[i];
495        pDHCPMSG->OPT[k++] = NibbleToHex(DHCP_CHADDR[3] >> 4);
496        pDHCPMSG->OPT[k++] = NibbleToHex(DHCP_CHADDR[3]);
497        pDHCPMSG->OPT[k++] = NibbleToHex(DHCP_CHADDR[4] >> 4);
498        pDHCPMSG->OPT[k++] = NibbleToHex(DHCP_CHADDR[4]);
499        pDHCPMSG->OPT[k++] = NibbleToHex(DHCP_CHADDR[5] >> 4);
500        pDHCPMSG->OPT[k++] = NibbleToHex(DHCP_CHADDR[5]);
501        pDHCPMSG->OPT[k - (i+6+1)] = i+6; // length of hostname
502
503        pDHCPMSG->OPT[k++] = dhcpParamRequest;
504        pDHCPMSG->OPT[k++] = 0x08;
505        pDHCPMSG->OPT[k++] = subnetMask;
506        pDHCPMSG->OPT[k++] = routersOnSubnet;
507        pDHCPMSG->OPT[k++] = dns;
508        pDHCPMSG->OPT[k++] = domainName;
509        pDHCPMSG->OPT[k++] = dhcpT1value;
510        pDHCPMSG->OPT[k++] = dhcpT2value;
511        pDHCPMSG->OPT[k++] = performRouterDiscovery;
512        pDHCPMSG->OPT[k++] = staticRoute;
513        pDHCPMSG->OPT[k++] = endOption;
514
515        for (i = k; i < OPT_SIZE; i++) pDHCPMSG->OPT[i] = 0;
516
517#ifdef _DHCP_DEBUG_
518        printf("> Send DHCP_REQUEST\r\n");
519#endif
520
521        sendto(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT);
522
523}
524
525/* SEND DHCP DHCPDECLINE */
526void send_DHCP_DECLINE(void)
527{
528        int i;
529        uint8_t ip[4];
530        uint16_t k = 0;
531
532        makeDHCPMSG();
533
534   k = 4;      // because MAGIC_COOKIE already made by makeDHCPMSG()
535
536        *((uint8_t*)(&pDHCPMSG->flags))   = ((DHCP_FLAGSUNICAST & 0xFF00)>> 8);
537        *((uint8_t*)(&pDHCPMSG->flags)+1) = (DHCP_FLAGSUNICAST & 0x00FF);
538
539        // Option Request Param.
540        pDHCPMSG->OPT[k++] = dhcpMessageType;
541        pDHCPMSG->OPT[k++] = 0x01;
542        pDHCPMSG->OPT[k++] = DHCP_DECLINE;
543
544        pDHCPMSG->OPT[k++] = dhcpClientIdentifier;
545        pDHCPMSG->OPT[k++] = 0x07;
546        pDHCPMSG->OPT[k++] = 0x01;
547        pDHCPMSG->OPT[k++] = DHCP_CHADDR[0];
548        pDHCPMSG->OPT[k++] = DHCP_CHADDR[1];
549        pDHCPMSG->OPT[k++] = DHCP_CHADDR[2];
550        pDHCPMSG->OPT[k++] = DHCP_CHADDR[3];
551        pDHCPMSG->OPT[k++] = DHCP_CHADDR[4];
552        pDHCPMSG->OPT[k++] = DHCP_CHADDR[5];
553
554        pDHCPMSG->OPT[k++] = dhcpRequestedIPaddr;
555        pDHCPMSG->OPT[k++] = 0x04;
556        pDHCPMSG->OPT[k++] = DHCP_allocated_ip[0];
557        pDHCPMSG->OPT[k++] = DHCP_allocated_ip[1];
558        pDHCPMSG->OPT[k++] = DHCP_allocated_ip[2];
559        pDHCPMSG->OPT[k++] = DHCP_allocated_ip[3];
560
561        pDHCPMSG->OPT[k++] = dhcpServerIdentifier;
562        pDHCPMSG->OPT[k++] = 0x04;
563        pDHCPMSG->OPT[k++] = DHCP_SIP[0];
564        pDHCPMSG->OPT[k++] = DHCP_SIP[1];
565        pDHCPMSG->OPT[k++] = DHCP_SIP[2];
566        pDHCPMSG->OPT[k++] = DHCP_SIP[3];
567
568        pDHCPMSG->OPT[k++] = endOption;
569
570        for (i = k; i < OPT_SIZE; i++) pDHCPMSG->OPT[i] = 0;
571
572        //send broadcasting packet
573        ip[0] = 0xFF;
574        ip[1] = 0xFF;
575        ip[2] = 0xFF;
576        ip[3] = 0xFF;
577
578#ifdef _DHCP_DEBUG_
579        printf("\r\n> Send DHCP_DECLINE\r\n");
580#endif
581
582        sendto(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT);
583}
584
585/* PARSE REPLY pDHCPMSG */
586int8_t parseDHCPMSG(void)
587{
588        uint8_t svr_addr[6];
589        uint16_t  svr_port;
590        uint16_t len;
591
592        uint8_t* p;
593        uint8_t* e;
594        uint8_t type = 0;
595        uint8_t opt_len;
596
597        if ((len = getSn_RX_RSR(DHCP_SOCKET)) > 0)
598        {
599                len = recvfrom(DHCP_SOCKET, (uint8_t *)pDHCPMSG, len, svr_addr, &svr_port);
600#ifdef _DHCP_DEBUG_
601                printf("DHCP message : %d.%d.%d.%d(%d) %d received. \r\n",svr_addr[0],svr_addr[1],svr_addr[2], svr_addr[3],svr_port, len);
602#endif
603        }
604        else return 0;
605
606        if (svr_port == DHCP_SERVER_PORT)
607        {       // compare mac address
608                if ( (pDHCPMSG->chaddr[0] != DHCP_CHADDR[0]) || (pDHCPMSG->chaddr[1] != DHCP_CHADDR[1]) ||
609                     (pDHCPMSG->chaddr[2] != DHCP_CHADDR[2]) || (pDHCPMSG->chaddr[3] != DHCP_CHADDR[3]) ||
610                     (pDHCPMSG->chaddr[4] != DHCP_CHADDR[4]) || (pDHCPMSG->chaddr[5] != DHCP_CHADDR[5])   )
611                {
612#ifdef _DHCP_DEBUG_
613            printf("No My DHCP Message. This message is ignored.\r\n");
614#endif
615                        return 0;
616                }
617
618        //compare DHCP server ip address
619        if ((DHCP_SIP[0]!=0) || (DHCP_SIP[1]!=0) || (DHCP_SIP[2]!=0) || (DHCP_SIP[3]!=0))
620                {
621            if( ((svr_addr[0]!=DHCP_SIP[0])|| (svr_addr[1]!=DHCP_SIP[1])|| (svr_addr[2]!=DHCP_SIP[2])|| (svr_addr[3]!=DHCP_SIP[3])) &&
622                ((svr_addr[0]!=DHCP_REAL_SIP[0])|| (svr_addr[1]!=DHCP_REAL_SIP[1])|| (svr_addr[2]!=DHCP_REAL_SIP[2])|| (svr_addr[3]!=DHCP_REAL_SIP[3]))  )
623            {
624#ifdef _DHCP_DEBUG_
625                printf("Another DHCP sever send a response message. This is ignored.\r\n");
626#endif
627                return 0;
628            }
629        }
630
631                p = (uint8_t *)(&pDHCPMSG->op);
632                p = p + 240;      // 240 = sizeof(RIP_MSG) + MAGIC_COOKIE size in RIP_MSG.opt - sizeof(RIP_MSG.opt)
633                e = p + (len - 240);
634
635                while ( p < e )
636                {
637                        switch ( *p )
638                        {
639                                case endOption :
640                                        p = e;   // for break while(p < e)
641                                        break;
642                                case padOption :
643                                        p++;
644                                        break;
645                                case dhcpMessageType :
646                                        p++;
647                                        p++;
648                                        type = *p++;
649                                        break;
650                                case subnetMask :
651                                        p++;
652                                        p++;
653                                        DHCP_allocated_sn[0] = *p++;
654                                        DHCP_allocated_sn[1] = *p++;
655                                        DHCP_allocated_sn[2] = *p++;
656                                        DHCP_allocated_sn[3] = *p++;
657                                        break;
658                                case routersOnSubnet :
659                                        p++;
660                                        opt_len = *p++;
661                                        DHCP_allocated_gw[0] = *p++;
662                                        DHCP_allocated_gw[1] = *p++;
663                                        DHCP_allocated_gw[2] = *p++;
664                                        DHCP_allocated_gw[3] = *p++;
665                                        p = p + (opt_len - 4);
666                                        break;
667                                case dns :
668                                        p++;
669                                        opt_len = *p++;
670                                        DHCP_allocated_dns[0] = *p++;
671                                        DHCP_allocated_dns[1] = *p++;
672                                        DHCP_allocated_dns[2] = *p++;
673                                        DHCP_allocated_dns[3] = *p++;
674                                        p = p + (opt_len - 4);
675                                        break;
676                                case dhcpIPaddrLeaseTime :
677                                        p++;
678                                        opt_len = *p++;
679                                        dhcp_lease_time  = *p++;
680                                        dhcp_lease_time  = (dhcp_lease_time << 8) + *p++;
681                                        dhcp_lease_time  = (dhcp_lease_time << 8) + *p++;
682                                        dhcp_lease_time  = (dhcp_lease_time << 8) + *p++;
683#ifdef _DHCP_DEBUG_
684                                        dhcp_lease_time = 10;
685#endif
686                                        break;
687                                case dhcpServerIdentifier :
688                                p++;
689                                opt_len = *p++;
690                                DHCP_SIP[0] = *p++;
691                                DHCP_SIP[1] = *p++;
692                                DHCP_SIP[2] = *p++;
693                                DHCP_SIP[3] = *p++;
694                    DHCP_REAL_SIP[0]=svr_addr[0];
695                    DHCP_REAL_SIP[1]=svr_addr[1];
696                    DHCP_REAL_SIP[2]=svr_addr[2];
697                    DHCP_REAL_SIP[3]=svr_addr[3];
698                                break;
699                                default :
700                                        p++;
701                                        opt_len = *p++;
702                                        p += opt_len;
703                                        break;
704                        } // switch
705                } // while
706        } // if
707        return  type;
708}
709
710uint8_t DHCP_run(void)
711{
712        uint8_t  type;
713        uint8_t  ret;
714
715        if (dhcp_state == STATE_DHCP_STOP) return DHCP_STOPPED;
716
717        if (getSn_SR(DHCP_SOCKET) != SOCK_UDP)
718           socket(DHCP_SOCKET, Sn_MR_UDP, DHCP_CLIENT_PORT, 0x00);
719
720        ret = DHCP_RUNNING;
721        type = parseDHCPMSG();
722
723        switch ( dhcp_state )
724        {
725                case STATE_DHCP_INIT     :
726                        DHCP_allocated_ip[0] = 0;
727                        DHCP_allocated_ip[1] = 0;
728                        DHCP_allocated_ip[2] = 0;
729                        DHCP_allocated_ip[3] = 0;
730                        send_DHCP_DISCOVER();
731                        dhcp_state = STATE_DHCP_DISCOVER;
732                        break;
733                case STATE_DHCP_DISCOVER :
734                        if (type == DHCP_OFFER)
735                        {
736#ifdef _DHCP_DEBUG_
737                                printf("> Receive DHCP_OFFER\r\n");
738#endif
739                DHCP_allocated_ip[0] = pDHCPMSG->yiaddr[0];
740                DHCP_allocated_ip[1] = pDHCPMSG->yiaddr[1];
741                DHCP_allocated_ip[2] = pDHCPMSG->yiaddr[2];
742                DHCP_allocated_ip[3] = pDHCPMSG->yiaddr[3];
743
744                                send_DHCP_REQUEST();
745                                dhcp_state = STATE_DHCP_REQUEST;
746                        }
747                        else
748                                ret = check_DHCP_timeout();
749                        break;
750
751                case STATE_DHCP_REQUEST :
752                        if (type == DHCP_ACK)
753                        {
754#ifdef _DHCP_DEBUG_
755                                printf("> Receive DHCP_ACK\r\n");
756#endif
757                                if (check_DHCP_leasedIP())
758                                {       // Network info assignment from DHCP
759                                        dhcp_ip_assign();
760                                        reset_DHCP_timeout();
761
762                                        dhcp_state = STATE_DHCP_LEASED;
763                                }
764                                else
765                                {       // IP address conflict occurred
766                                        reset_DHCP_timeout();
767                                        dhcp_ip_conflict();
768                                    dhcp_state = STATE_DHCP_INIT;
769                                }
770                        }
771                        else if (type == DHCP_NAK)
772                        {
773#ifdef _DHCP_DEBUG_
774                                printf("> Receive DHCP_NACK\r\n");
775#endif
776                                reset_DHCP_timeout();
777
778                                dhcp_state = STATE_DHCP_DISCOVER;
779                        }
780                        else
781                                ret = check_DHCP_timeout();
782                        break;
783
784                case STATE_DHCP_LEASED :
785                        ret = DHCP_IP_LEASED;
786                        if ((dhcp_lease_time != INFINITE_LEASETIME) && ((dhcp_lease_time/2) < dhcp_tick_1s))
787                        {
788#ifdef _DHCP_DEBUG_
789                                printf("> Maintains the IP address \r\n");
790#endif
791                                type = 0;
792                                OLD_allocated_ip[0] = DHCP_allocated_ip[0];
793                                OLD_allocated_ip[1] = DHCP_allocated_ip[1];
794                                OLD_allocated_ip[2] = DHCP_allocated_ip[2];
795                                OLD_allocated_ip[3] = DHCP_allocated_ip[3];
796
797                                DHCP_XID++;
798
799                                send_DHCP_REQUEST();
800
801                                reset_DHCP_timeout();
802
803                                dhcp_state = STATE_DHCP_REREQUEST;
804                        }
805                        break;
806
807                case STATE_DHCP_REREQUEST :
808                        ret = DHCP_IP_LEASED;
809                        if (type == DHCP_ACK)
810                        {
811                                dhcp_retry_count = 0;
812                                if (OLD_allocated_ip[0] != DHCP_allocated_ip[0] ||
813                                    OLD_allocated_ip[1] != DHCP_allocated_ip[1] ||
814                                    OLD_allocated_ip[2] != DHCP_allocated_ip[2] ||
815                                    OLD_allocated_ip[3] != DHCP_allocated_ip[3])
816                                {
817                                        ret = DHCP_IP_CHANGED;
818                                        dhcp_ip_update();
819#ifdef _DHCP_DEBUG_
820                                        printf(">IP changed.\r\n");
821#endif
822
823                                }
824#ifdef _DHCP_DEBUG_
825                                else printf(">IP is continued.\r\n");
826#endif
827                                reset_DHCP_timeout();
828                                dhcp_state = STATE_DHCP_LEASED;
829                        }
830                        else if (type == DHCP_NAK)
831                        {
832#ifdef _DHCP_DEBUG_
833                                printf("> Receive DHCP_NACK, Failed to maintain ip\r\n");
834#endif
835                                reset_DHCP_timeout();
836
837                                dhcp_state = STATE_DHCP_DISCOVER;
838                        }
839                        else
840                                ret = check_DHCP_timeout();
841                        break;
842                default :
843                        break;
844        }
845
846        return ret;
847}
848
849void    DHCP_stop(void)
850{
851   close(DHCP_SOCKET);
852   dhcp_state = STATE_DHCP_STOP;
853}
854
855uint8_t check_DHCP_timeout(void)
856{
857        uint8_t ret = DHCP_RUNNING;
858
859        if (dhcp_retry_count < MAX_DHCP_RETRY) {
860                if (dhcp_tick_next < dhcp_tick_1s) {
861
862                        switch ( dhcp_state ) {
863                                case STATE_DHCP_DISCOVER :
864//                                      printf("<<timeout>> state : STATE_DHCP_DISCOVER\r\n");
865                                        send_DHCP_DISCOVER();
866                                break;
867
868                                case STATE_DHCP_REQUEST :
869//                                      printf("<<timeout>> state : STATE_DHCP_REQUEST\r\n");
870
871                                        send_DHCP_REQUEST();
872                                break;
873
874                                case STATE_DHCP_REREQUEST :
875//                                      printf("<<timeout>> state : STATE_DHCP_REREQUEST\r\n");
876
877                                        send_DHCP_REQUEST();
878                                break;
879
880                                default :
881                                break;
882                        }
883
884                        dhcp_tick_1s = 0;
885                        dhcp_tick_next = dhcp_tick_1s + DHCP_WAIT_TIME;
886                        dhcp_retry_count++;
887                }
888        } else { // timeout occurred
889
890                switch(dhcp_state) {
891                        case STATE_DHCP_DISCOVER:
892                                dhcp_state = STATE_DHCP_INIT;
893                                ret = DHCP_FAILED;
894                                break;
895                        case STATE_DHCP_REQUEST:
896                        case STATE_DHCP_REREQUEST:
897                                send_DHCP_DISCOVER();
898                                dhcp_state = STATE_DHCP_DISCOVER;
899                                break;
900                        default :
901                                break;
902                }
903                reset_DHCP_timeout();
904        }
905        return ret;
906}
907
908int8_t check_DHCP_leasedIP(void)
909{
910        uint8_t tmp;
911        int32_t ret;
912
913        //WIZchip RCR value changed for ARP Timeout count control
914        tmp = getRCR();
915        setRCR(0x03);
916
917        // IP conflict detection : ARP request - ARP reply
918        // Broadcasting ARP Request for check the IP conflict using UDP sendto() function
919        ret = sendto(DHCP_SOCKET, (uint8_t *)"CHECK_IP_CONFLICT", 17, DHCP_allocated_ip, 5000);
920
921        // RCR value restore
922        setRCR(tmp);
923
924        if(ret == SOCKERR_TIMEOUT) {
925                // UDP send Timeout occurred : allocated IP address is unique, DHCP Success
926
927#ifdef _DHCP_DEBUG_
928                printf("\r\n> Check leased IP - OK\r\n");
929#endif
930
931                return 1;
932        } else {
933                // Received ARP reply or etc : IP address conflict occur, DHCP Failed
934                send_DHCP_DECLINE();
935
936                ret = dhcp_tick_1s;
937                while((dhcp_tick_1s - ret) < 2) ;   // wait for 1s over; wait to complete to send DECLINE message;
938
939                return 0;
940        }
941}
942
943void DHCP_init(uint8_t s, uint8_t * buf)
944{
945   uint8_t zeroip[4] = {0,0,0,0};
946   getSHAR(DHCP_CHADDR);
947   if((DHCP_CHADDR[0] | DHCP_CHADDR[1]  | DHCP_CHADDR[2] | DHCP_CHADDR[3] | DHCP_CHADDR[4] | DHCP_CHADDR[5]) == 0x00)
948   {
949      // assigning temporary mac address, you should be set SHAR before call this function.
950      DHCP_CHADDR[0] = 0x00;
951      DHCP_CHADDR[1] = 0x08;
952      DHCP_CHADDR[2] = 0xdc;
953      DHCP_CHADDR[3] = 0x00;
954      DHCP_CHADDR[4] = 0x00;
955      DHCP_CHADDR[5] = 0x00;
956      setSHAR(DHCP_CHADDR);
957   }
958
959        DHCP_SOCKET = s; // SOCK_DHCP
960        pDHCPMSG = (RIP_MSG*)buf;
961        DHCP_XID = 0x12345678;
962        {
963                DHCP_XID += DHCP_CHADDR[3];
964                DHCP_XID += DHCP_CHADDR[4];
965                DHCP_XID += DHCP_CHADDR[5];
966                DHCP_XID += (DHCP_CHADDR[3] ^ DHCP_CHADDR[4] ^ DHCP_CHADDR[5]);
967        }
968        // WIZchip Netinfo Clear
969        setSIPR(zeroip);
970        setGAR(zeroip);
971
972        reset_DHCP_timeout();
973        dhcp_state = STATE_DHCP_INIT;
974}
975
976
977/* Reset the DHCP timeout count and retry count. */
978void reset_DHCP_timeout(void)
979{
980        dhcp_tick_1s = 0;
981        dhcp_tick_next = DHCP_WAIT_TIME;
982        dhcp_retry_count = 0;
983}
984
985void DHCP_time_handler(void)
986{
987        dhcp_tick_1s++;
988}
989
990void getIPfromDHCP(uint8_t* ip)
991{
992        ip[0] = DHCP_allocated_ip[0];
993        ip[1] = DHCP_allocated_ip[1];
994        ip[2] = DHCP_allocated_ip[2];
995        ip[3] = DHCP_allocated_ip[3];
996}
997
998void getGWfromDHCP(uint8_t* ip)
999{
1000        ip[0] =DHCP_allocated_gw[0];
1001        ip[1] =DHCP_allocated_gw[1];
1002        ip[2] =DHCP_allocated_gw[2];
1003        ip[3] =DHCP_allocated_gw[3];
1004}
1005
1006void getSNfromDHCP(uint8_t* ip)
1007{
1008   ip[0] = DHCP_allocated_sn[0];
1009   ip[1] = DHCP_allocated_sn[1];
1010   ip[2] = DHCP_allocated_sn[2];
1011   ip[3] = DHCP_allocated_sn[3];
1012}
1013
1014void getDNSfromDHCP(uint8_t* ip)
1015{
1016   ip[0] = DHCP_allocated_dns[0];
1017   ip[1] = DHCP_allocated_dns[1];
1018   ip[2] = DHCP_allocated_dns[2];
1019   ip[3] = DHCP_allocated_dns[3];
1020}
1021
1022uint32_t getDHCPLeasetime(void)
1023{
1024        return dhcp_lease_time;
1025}
1026
1027char NibbleToHex(uint8_t nibble)
1028{
1029  nibble &= 0x0F;
1030  if (nibble <= 9)
1031    return nibble + '0';
1032  else
1033    return nibble + ('A'-0x0A);
1034}
1035
1036
Note: See TracBrowser for help on using the repository browser.