diff options
Diffstat (limited to 'drivers/wiznet5k/internet/dhcp/dhcp.c')
| -rw-r--r-- | drivers/wiznet5k/internet/dhcp/dhcp.c | 978 | 
1 files changed, 978 insertions, 0 deletions
| diff --git a/drivers/wiznet5k/internet/dhcp/dhcp.c b/drivers/wiznet5k/internet/dhcp/dhcp.c new file mode 100644 index 000000000..574758259 --- /dev/null +++ b/drivers/wiznet5k/internet/dhcp/dhcp.c @@ -0,0 +1,978 @@ +//***************************************************************************** +// +//! \file dhcp.c +//! \brief DHCP APIs implement file. +//! \details Processig DHCP protocol as DISCOVER, OFFER, REQUEST, ACK, NACK and DECLINE. +//! \version 1.1.0 +//! \date 2013/11/18 +//! \par  Revision history +//!       <2013/11/18> 1st Release +//!       <2012/12/20> V1.1.0 +//!         1. Optimize code +//!         2. Add reg_dhcp_cbfunc() +//!         3. Add DHCP_stop()  +//!         4. Integrate check_DHCP_state() & DHCP_run() to DHCP_run() +//!         5. Don't care system endian +//!         6. Add comments +//!       <2012/12/26> V1.1.1 +//!         1. Modify variable declaration: dhcp_tick_1s is declared volatile for code optimization +//! \author Eric Jung & MidnightCow +//! \copyright +//! +//! Copyright (c)  2013, WIZnet Co., LTD. +//! All rights reserved. +//!  +//! Redistribution and use in source and binary forms, with or without  +//! modification, are permitted provided that the following conditions  +//! are met:  +//!  +//!     * Redistributions of source code must retain the above copyright  +//! notice, this list of conditions and the following disclaimer.  +//!     * Redistributions in binary form must reproduce the above copyright +//! notice, this list of conditions and the following disclaimer in the +//! documentation and/or other materials provided with the distribution.  +//!     * Neither the name of the <ORGANIZATION> nor the names of its  +//! contributors may be used to endorse or promote products derived  +//! from this software without specific prior written permission.  +//!  +//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE  +//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE  +//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR  +//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF  +//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN  +//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)  +//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF  +//! THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** + +//#include "Ethernet/socket.h" +//#include "Internet/DHCP/dhcp.h" +#include "../../Ethernet/socket.h" +#include "dhcp.h" + +/* If you want to display debug & processing message, Define _DHCP_DEBUG_ in dhcp.h */ + +#ifdef _DHCP_DEBUG_ +   #include <stdio.h> +#endif    + +/* DHCP state machine. */ +#define STATE_DHCP_INIT          0        ///< Initialize +#define STATE_DHCP_DISCOVER      1        ///< send DISCOVER and wait OFFER +#define STATE_DHCP_REQUEST       2        ///< send REQEUST and wait ACK or NACK +#define STATE_DHCP_LEASED        3        ///< ReceiveD ACK and IP leased +#define STATE_DHCP_REREQUEST     4        ///< send REQUEST for maintaining leased IP +#define STATE_DHCP_RELEASE       5        ///< No use +#define STATE_DHCP_STOP          6        ///< Stop processing DHCP + +#define DHCP_FLAGSBROADCAST      0x8000   ///< The broadcast value of flags in @ref RIP_MSG  +#define DHCP_FLAGSUNICAST        0x0000   ///< The unicast   value of flags in @ref RIP_MSG + +/* DHCP message OP code */ +#define DHCP_BOOTREQUEST         1        ///< Request Message used in op of @ref RIP_MSG +#define DHCP_BOOTREPLY           2        ///< Reply Message used i op of @ref RIP_MSG + +/* DHCP message type */ +#define DHCP_DISCOVER            1        ///< DISCOVER message in OPT of @ref RIP_MSG +#define DHCP_OFFER               2        ///< OFFER message in OPT of @ref RIP_MSG +#define DHCP_REQUEST             3        ///< REQUEST message in OPT of @ref RIP_MSG +#define DHCP_DECLINE             4        ///< DECLINE message in OPT of @ref RIP_MSG +#define DHCP_ACK                 5        ///< ACK message in OPT of @ref RIP_MSG +#define DHCP_NAK                 6        ///< NACK message in OPT of @ref RIP_MSG +#define DHCP_RELEASE             7        ///< RELEASE message in OPT of @ref RIP_MSG. No use +#define DHCP_INFORM              8        ///< INFORM message in OPT of @ref RIP_MSG. No use + +#define DHCP_HTYPE10MB           1        ///< Used in type of @ref RIP_MSG +#define DHCP_HTYPE100MB          2        ///< Used in type of @ref RIP_MSG + +#define DHCP_HLENETHERNET        6        ///< Used in hlen of @ref RIP_MSG +#define DHCP_HOPS                0        ///< Used in hops of @ref RIP_MSG +#define DHCP_SECS                0        ///< Used in secs of @ref RIP_MSG + +#define INFINITE_LEASETIME       0xffffffff	///< Infinite lease time + +#define OPT_SIZE                 312               /// Max OPT size of @ref RIP_MSG +#define RIP_MSG_SIZE             (236+OPT_SIZE)    /// Max size of @ref RIP_MSG + +/*  + * @brief DHCP option and value (cf. RFC1533) + */ +enum +{ +   padOption               = 0, +   subnetMask              = 1, +   timerOffset             = 2, +   routersOnSubnet         = 3, +   timeServer              = 4, +   nameServer              = 5, +   dns                     = 6, +   logServer               = 7, +   cookieServer            = 8, +   lprServer               = 9, +   impressServer           = 10, +   resourceLocationServer	= 11, +   hostName                = 12, +   bootFileSize            = 13, +   meritDumpFile           = 14, +   domainName              = 15, +   swapServer              = 16, +   rootPath                = 17, +   extentionsPath          = 18, +   IPforwarding            = 19, +   nonLocalSourceRouting   = 20, +   policyFilter            = 21, +   maxDgramReasmSize       = 22, +   defaultIPTTL            = 23, +   pathMTUagingTimeout     = 24, +   pathMTUplateauTable     = 25, +   ifMTU                   = 26, +   allSubnetsLocal         = 27, +   broadcastAddr           = 28, +   performMaskDiscovery    = 29, +   maskSupplier            = 30, +   performRouterDiscovery  = 31, +   routerSolicitationAddr  = 32, +   staticRoute             = 33, +   trailerEncapsulation    = 34, +   arpCacheTimeout         = 35, +   ethernetEncapsulation   = 36, +   tcpDefaultTTL           = 37, +   tcpKeepaliveInterval    = 38, +   tcpKeepaliveGarbage     = 39, +   nisDomainName           = 40, +   nisServers              = 41, +   ntpServers              = 42, +   vendorSpecificInfo      = 43, +   netBIOSnameServer       = 44, +   netBIOSdgramDistServer	= 45, +   netBIOSnodeType         = 46, +   netBIOSscope            = 47, +   xFontServer             = 48, +   xDisplayManager         = 49, +   dhcpRequestedIPaddr     = 50, +   dhcpIPaddrLeaseTime     = 51, +   dhcpOptionOverload      = 52, +   dhcpMessageType         = 53, +   dhcpServerIdentifier    = 54, +   dhcpParamRequest        = 55, +   dhcpMsg                 = 56, +   dhcpMaxMsgSize          = 57, +   dhcpT1value             = 58, +   dhcpT2value             = 59, +   dhcpClassIdentifier     = 60, +   dhcpClientIdentifier    = 61, +   endOption               = 255 +}; + +/* + * @brief DHCP message format + */  +typedef struct { +	uint8_t  op;            ///< @ref DHCP_BOOTREQUEST or @ref DHCP_BOOTREPLY +	uint8_t  htype;         ///< @ref DHCP_HTYPE10MB or @ref DHCP_HTYPE100MB +	uint8_t  hlen;          ///< @ref DHCP_HLENETHERNET +	uint8_t  hops;          ///< @ref DHCP_HOPS +	uint32_t xid;           ///< @ref DHCP_XID  This increase one every DHCP transaction. +	uint16_t secs;          ///< @ref DHCP_SECS +	uint16_t flags;         ///< @ref DHCP_FLAGSBROADCAST or @ref DHCP_FLAGSUNICAST +	uint8_t  ciaddr[4];     ///< @ref Request IP to DHCP sever +	uint8_t  yiaddr[4];     ///< @ref Offered IP from DHCP server +	uint8_t  siaddr[4];     ///< No use  +	uint8_t  giaddr[4];     ///< No use +	uint8_t  chaddr[16];    ///< DHCP client 6bytes MAC address. Others is filled to zero +	uint8_t  sname[64];     ///< No use +	uint8_t  file[128];     ///< No use +	uint8_t  OPT[OPT_SIZE]; ///< Option +} RIP_MSG; + + + +uint8_t DHCP_SOCKET;                      // Socket number for DHCP + +uint8_t DHCP_SIP[4];                      // DHCP Server IP address + +// Network information from DHCP Server +uint8_t OLD_allocated_ip[4]   = {0, };    // Previous IP address +uint8_t DHCP_allocated_ip[4]  = {0, };    // IP address from DHCP +uint8_t DHCP_allocated_gw[4]  = {0, };    // Gateway address from DHCP +uint8_t DHCP_allocated_sn[4]  = {0, };    // Subnet mask from DHCP +uint8_t DHCP_allocated_dns[4] = {0, };    // DNS address from DHCP + + +int8_t   dhcp_state        = STATE_DHCP_INIT;   // DHCP state +int8_t   dhcp_retry_count  = 0;                  + +uint32_t dhcp_lease_time   			= INFINITE_LEASETIME; +volatile uint32_t dhcp_tick_1s      = 0;                 // unit 1 second +uint32_t dhcp_tick_next    			= DHCP_WAIT_TIME ; + +uint32_t DHCP_XID;      // Any number + +RIP_MSG* pDHCPMSG;      // Buffer pointer for DHCP processing + +uint8_t HOST_NAME[] = DCHP_HOST_NAME;   + +uint8_t DHCP_CHADDR[6]; // DHCP Client MAC address. + +/* The default callback function */ +void default_ip_assign(void); +void default_ip_update(void); +void default_ip_conflict(void); + +/* Callback handler */ +void (*dhcp_ip_assign)(void)   = default_ip_assign;     /* handler to be called when the IP address from DHCP server is first assigned */ +void (*dhcp_ip_update)(void)   = default_ip_update;     /* handler to be called when the IP address from DHCP server is updated */ +void (*dhcp_ip_conflict)(void) = default_ip_conflict;   /* handler to be called when the IP address from DHCP server is conflict */ + +void reg_dhcp_cbfunc(void(*ip_assign)(void), void(*ip_update)(void), void(*ip_conflict)(void)); + + +/* send DISCOVER message to DHCP server */ +void     send_DHCP_DISCOVER(void); + +/* send REQEUST message to DHCP server */ +void     send_DHCP_REQUEST(void); + +/* send DECLINE message to DHCP server */ +void     send_DHCP_DECLINE(void); + +/* IP conflict check by sending ARP-request to leased IP and wait ARP-response. */ +int8_t   check_DHCP_leasedIP(void); + +/* check the timeout in DHCP process */ +uint8_t  check_DHCP_timeout(void); + +/* Intialize to timeout process.  */ +void     reset_DHCP_timeout(void); + +/* Parse message as OFFER and ACK and NACK from DHCP server.*/ +int8_t   parseDHCPCMSG(void); + +/* The default handler of ip assign first */ +void default_ip_assign(void) +{ +   setSIPR(DHCP_allocated_ip); +   setSUBR(DHCP_allocated_sn); +   setGAR (DHCP_allocated_gw); +} + +/* The default handler of ip changed */ +void default_ip_update(void) +{ +	/* WIZchip Software Reset */ +   setMR(MR_RST); +   getMR(); // for delay +   default_ip_assign(); +   setSHAR(DHCP_CHADDR); +} + +/* The default handler of ip changed */ +void default_ip_conflict(void) +{ +	// WIZchip Software Reset +	setMR(MR_RST); +	getMR(); // for delay +	setSHAR(DHCP_CHADDR); +} + +/* register the call back func. */ +void reg_dhcp_cbfunc(void(*ip_assign)(void), void(*ip_update)(void), void(*ip_conflict)(void)) +{ +   dhcp_ip_assign   = default_ip_assign; +   dhcp_ip_update   = default_ip_update; +   dhcp_ip_conflict = default_ip_conflict; +   if(ip_assign)   dhcp_ip_assign = ip_assign; +   if(ip_update)   dhcp_ip_update = ip_update; +   if(ip_conflict) dhcp_ip_conflict = ip_conflict; +} + +/* make the common DHCP message */ +void makeDHCPMSG(void) +{ +   uint8_t  bk_mac[6]; +   uint8_t* ptmp; +   uint8_t  i; +   getSHAR(bk_mac); +	pDHCPMSG->op      = DHCP_BOOTREQUEST; +	pDHCPMSG->htype   = DHCP_HTYPE10MB; +	pDHCPMSG->hlen    = DHCP_HLENETHERNET; +	pDHCPMSG->hops    = DHCP_HOPS; +	ptmp              = (uint8_t*)(&pDHCPMSG->xid); +	*(ptmp+0)         = (uint8_t)((DHCP_XID & 0xFF000000) >> 24); +	*(ptmp+1)         = (uint8_t)((DHCP_XID & 0x00FF0000) >> 16); +   *(ptmp+2)         = (uint8_t)((DHCP_XID & 0x0000FF00) >>  8); +	*(ptmp+3)         = (uint8_t)((DHCP_XID & 0x000000FF) >>  0);    +	pDHCPMSG->secs    = DHCP_SECS; +	ptmp              = (uint8_t*)(&pDHCPMSG->flags);	 +	*(ptmp+0)         = (uint8_t)((DHCP_FLAGSBROADCAST & 0xFF00) >> 8); +	*(ptmp+1)         = (uint8_t)((DHCP_FLAGSBROADCAST & 0x00FF) >> 0); + +	pDHCPMSG->ciaddr[0] = 0; +	pDHCPMSG->ciaddr[1] = 0; +	pDHCPMSG->ciaddr[2] = 0; +	pDHCPMSG->ciaddr[3] = 0; + +	pDHCPMSG->yiaddr[0] = 0; +	pDHCPMSG->yiaddr[1] = 0; +	pDHCPMSG->yiaddr[2] = 0; +	pDHCPMSG->yiaddr[3] = 0; + +	pDHCPMSG->siaddr[0] = 0; +	pDHCPMSG->siaddr[1] = 0; +	pDHCPMSG->siaddr[2] = 0; +	pDHCPMSG->siaddr[3] = 0; + +	pDHCPMSG->giaddr[0] = 0; +	pDHCPMSG->giaddr[1] = 0; +	pDHCPMSG->giaddr[2] = 0; +	pDHCPMSG->giaddr[3] = 0; + +	pDHCPMSG->chaddr[0] = DHCP_CHADDR[0]; +	pDHCPMSG->chaddr[1] = DHCP_CHADDR[1]; +	pDHCPMSG->chaddr[2] = DHCP_CHADDR[2]; +	pDHCPMSG->chaddr[3] = DHCP_CHADDR[3]; +	pDHCPMSG->chaddr[4] = DHCP_CHADDR[4]; +	pDHCPMSG->chaddr[5] = DHCP_CHADDR[5]; + +	for (i = 6; i < 16; i++)  pDHCPMSG->chaddr[i] = 0; +	for (i = 0; i < 64; i++)  pDHCPMSG->sname[i]  = 0; +	for (i = 0; i < 128; i++) pDHCPMSG->file[i]   = 0; + +	// MAGIC_COOKIE +	pDHCPMSG->OPT[0] = (uint8_t)((MAGIC_COOKIE & 0xFF000000) >> 24); +	pDHCPMSG->OPT[1] = (uint8_t)((MAGIC_COOKIE & 0x00FF0000) >> 16); +	pDHCPMSG->OPT[2] = (uint8_t)((MAGIC_COOKIE & 0x0000FF00) >>  8); +	pDHCPMSG->OPT[3] = (uint8_t) (MAGIC_COOKIE & 0x000000FF) >>  0; +} + +/* SEND DHCP DISCOVER */ +void send_DHCP_DISCOVER(void) +{ +	uint16_t i; +	uint8_t ip[4]; +	uint16_t k = 0; +    +   makeDHCPMSG(); + +   k = 4;     // because MAGIC_COOKIE already made by makeDHCPMSG() +    +	// Option Request Param +	pDHCPMSG->OPT[k++] = dhcpMessageType; +	pDHCPMSG->OPT[k++] = 0x01; +	pDHCPMSG->OPT[k++] = DHCP_DISCOVER; +	 +	// Client identifier +	pDHCPMSG->OPT[k++] = dhcpClientIdentifier; +	pDHCPMSG->OPT[k++] = 0x07; +	pDHCPMSG->OPT[k++] = 0x01; +	pDHCPMSG->OPT[k++] = DHCP_CHADDR[0]; +	pDHCPMSG->OPT[k++] = DHCP_CHADDR[1]; +	pDHCPMSG->OPT[k++] = DHCP_CHADDR[2]; +	pDHCPMSG->OPT[k++] = DHCP_CHADDR[3]; +	pDHCPMSG->OPT[k++] = DHCP_CHADDR[4]; +	pDHCPMSG->OPT[k++] = DHCP_CHADDR[5]; +	 +	// host name +	pDHCPMSG->OPT[k++] = hostName; +	pDHCPMSG->OPT[k++] = 0;          // fill zero length of hostname  +	for(i = 0 ; HOST_NAME[i] != 0; i++) +   	pDHCPMSG->OPT[k++] = HOST_NAME[i]; +	pDHCPMSG->OPT[k++] = DHCP_CHADDR[3]; +	pDHCPMSG->OPT[k++] = DHCP_CHADDR[4]; +	pDHCPMSG->OPT[k++] = DHCP_CHADDR[5]; +	pDHCPMSG->OPT[k - (i+3+1)] = i+3; // length of hostname + +	pDHCPMSG->OPT[k++] = dhcpParamRequest; +	pDHCPMSG->OPT[k++] = 0x06;	// length of request +	pDHCPMSG->OPT[k++] = subnetMask; +	pDHCPMSG->OPT[k++] = routersOnSubnet; +	pDHCPMSG->OPT[k++] = dns; +	pDHCPMSG->OPT[k++] = domainName; +	pDHCPMSG->OPT[k++] = dhcpT1value; +	pDHCPMSG->OPT[k++] = dhcpT2value; +	pDHCPMSG->OPT[k++] = endOption; + +	for (i = k; i < OPT_SIZE; i++) pDHCPMSG->OPT[i] = 0; + +	// send broadcasting packet +	ip[0] = 255; +	ip[1] = 255; +	ip[2] = 255; +	ip[3] = 255; + +#ifdef _DHCP_DEBUG_ +	printf("> Send DHCP_DISCOVER\r\n"); +#endif + +	sendto(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT); +} + +/* SEND DHCP REQUEST */ +void send_DHCP_REQUEST(void) +{ +	int i; +	uint8_t ip[4]; +	uint16_t k = 0; + +   makeDHCPMSG(); + +   if(dhcp_state == STATE_DHCP_LEASED || dhcp_state == STATE_DHCP_REREQUEST) +   { +   	*((uint8_t*)(&pDHCPMSG->flags))   = ((DHCP_FLAGSUNICAST & 0xFF00)>> 8); +   	*((uint8_t*)(&pDHCPMSG->flags)+1) = (DHCP_FLAGSUNICAST & 0x00FF); +   	pDHCPMSG->ciaddr[0] = DHCP_allocated_ip[0]; +   	pDHCPMSG->ciaddr[1] = DHCP_allocated_ip[1]; +   	pDHCPMSG->ciaddr[2] = DHCP_allocated_ip[2]; +   	pDHCPMSG->ciaddr[3] = DHCP_allocated_ip[3]; +   	ip[0] = DHCP_SIP[0]; +   	ip[1] = DHCP_SIP[1]; +   	ip[2] = DHCP_SIP[2]; +   	ip[3] = DHCP_SIP[3];   	   	   	 +   } +   else +   { +   	ip[0] = 255; +   	ip[1] = 255; +   	ip[2] = 255; +   	ip[3] = 255;   	   	   	 +   } +    +   k = 4;      // because MAGIC_COOKIE already made by makeDHCPMSG() +	 +	// Option Request Param. +	pDHCPMSG->OPT[k++] = dhcpMessageType; +	pDHCPMSG->OPT[k++] = 0x01; +	pDHCPMSG->OPT[k++] = DHCP_REQUEST; + +	pDHCPMSG->OPT[k++] = dhcpClientIdentifier; +	pDHCPMSG->OPT[k++] = 0x07; +	pDHCPMSG->OPT[k++] = 0x01; +	pDHCPMSG->OPT[k++] = DHCP_CHADDR[0]; +	pDHCPMSG->OPT[k++] = DHCP_CHADDR[1]; +	pDHCPMSG->OPT[k++] = DHCP_CHADDR[2]; +	pDHCPMSG->OPT[k++] = DHCP_CHADDR[3]; +	pDHCPMSG->OPT[k++] = DHCP_CHADDR[4]; +	pDHCPMSG->OPT[k++] = DHCP_CHADDR[5]; + +   if(ip[3] == 255)  // if(dchp_state == STATE_DHCP_LEASED || dchp_state == DHCP_REREQUEST_STATE) +   { +		pDHCPMSG->OPT[k++] = dhcpRequestedIPaddr; +		pDHCPMSG->OPT[k++] = 0x04; +		pDHCPMSG->OPT[k++] = DHCP_allocated_ip[0]; +		pDHCPMSG->OPT[k++] = DHCP_allocated_ip[1]; +		pDHCPMSG->OPT[k++] = DHCP_allocated_ip[2]; +		pDHCPMSG->OPT[k++] = DHCP_allocated_ip[3]; +	 +		pDHCPMSG->OPT[k++] = dhcpServerIdentifier; +		pDHCPMSG->OPT[k++] = 0x04; +		pDHCPMSG->OPT[k++] = DHCP_SIP[0]; +		pDHCPMSG->OPT[k++] = DHCP_SIP[1]; +		pDHCPMSG->OPT[k++] = DHCP_SIP[2]; +		pDHCPMSG->OPT[k++] = DHCP_SIP[3]; +	} + +	// host name +	pDHCPMSG->OPT[k++] = hostName; +	pDHCPMSG->OPT[k++] = 0; // length of hostname +	for(i = 0 ; HOST_NAME[i] != 0; i++) +   	pDHCPMSG->OPT[k++] = HOST_NAME[i]; +	pDHCPMSG->OPT[k++] = DHCP_CHADDR[3]; +	pDHCPMSG->OPT[k++] = DHCP_CHADDR[4]; +	pDHCPMSG->OPT[k++] = DHCP_CHADDR[5]; +	pDHCPMSG->OPT[k - (i+3+1)] = i+3; // length of hostname +	 +	pDHCPMSG->OPT[k++] = dhcpParamRequest; +	pDHCPMSG->OPT[k++] = 0x08; +	pDHCPMSG->OPT[k++] = subnetMask; +	pDHCPMSG->OPT[k++] = routersOnSubnet; +	pDHCPMSG->OPT[k++] = dns; +	pDHCPMSG->OPT[k++] = domainName; +	pDHCPMSG->OPT[k++] = dhcpT1value; +	pDHCPMSG->OPT[k++] = dhcpT2value; +	pDHCPMSG->OPT[k++] = performRouterDiscovery; +	pDHCPMSG->OPT[k++] = staticRoute; +	pDHCPMSG->OPT[k++] = endOption; + +	for (i = k; i < OPT_SIZE; i++) pDHCPMSG->OPT[i] = 0; + +#ifdef _DHCP_DEBUG_ +	printf("> Send DHCP_REQUEST\r\n"); +#endif +	 +	sendto(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT); + +} + +/* SEND DHCP DHCPDECLINE */ +void send_DHCP_DECLINE(void) +{ +	int i; +	uint8_t ip[4]; +	uint16_t k = 0; +	 +	makeDHCPMSG(); + +   k = 4;      // because MAGIC_COOKIE already made by makeDHCPMSG() +    +	*((uint8_t*)(&pDHCPMSG->flags))   = ((DHCP_FLAGSUNICAST & 0xFF00)>> 8); +	*((uint8_t*)(&pDHCPMSG->flags)+1) = (DHCP_FLAGSUNICAST & 0x00FF); + +	// Option Request Param. +	pDHCPMSG->OPT[k++] = dhcpMessageType; +	pDHCPMSG->OPT[k++] = 0x01; +	pDHCPMSG->OPT[k++] = DHCP_DECLINE; + +	pDHCPMSG->OPT[k++] = dhcpClientIdentifier; +	pDHCPMSG->OPT[k++] = 0x07; +	pDHCPMSG->OPT[k++] = 0x01; +	pDHCPMSG->OPT[k++] = DHCP_CHADDR[0]; +	pDHCPMSG->OPT[k++] = DHCP_CHADDR[1]; +	pDHCPMSG->OPT[k++] = DHCP_CHADDR[2]; +	pDHCPMSG->OPT[k++] = DHCP_CHADDR[3]; +	pDHCPMSG->OPT[k++] = DHCP_CHADDR[4]; +	pDHCPMSG->OPT[k++] = DHCP_CHADDR[5]; + +	pDHCPMSG->OPT[k++] = dhcpRequestedIPaddr; +	pDHCPMSG->OPT[k++] = 0x04; +	pDHCPMSG->OPT[k++] = DHCP_allocated_ip[0]; +	pDHCPMSG->OPT[k++] = DHCP_allocated_ip[1]; +	pDHCPMSG->OPT[k++] = DHCP_allocated_ip[2]; +	pDHCPMSG->OPT[k++] = DHCP_allocated_ip[3]; + +	pDHCPMSG->OPT[k++] = dhcpServerIdentifier; +	pDHCPMSG->OPT[k++] = 0x04; +	pDHCPMSG->OPT[k++] = DHCP_SIP[0]; +	pDHCPMSG->OPT[k++] = DHCP_SIP[1]; +	pDHCPMSG->OPT[k++] = DHCP_SIP[2]; +	pDHCPMSG->OPT[k++] = DHCP_SIP[3]; + +	pDHCPMSG->OPT[k++] = endOption; + +	for (i = k; i < OPT_SIZE; i++) pDHCPMSG->OPT[i] = 0; + +	//send broadcasting packet +	ip[0] = 0xFF; +	ip[1] = 0xFF; +	ip[2] = 0xFF; +	ip[3] = 0xFF; + +#ifdef _DHCP_DEBUG_ +	printf("\r\n> Send DHCP_DECLINE\r\n"); +#endif + +	sendto(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT); +} + +/* PARSE REPLY pDHCPMSG */ +int8_t parseDHCPMSG(void) +{ +	uint8_t svr_addr[6]; +	uint16_t  svr_port; +	uint16_t len; + +	uint8_t * p; +	uint8_t * e; +	uint8_t type; +	uint8_t opt_len; +    +   if((len = getSn_RX_RSR(DHCP_SOCKET)) > 0) +   { +   	len = recvfrom(DHCP_SOCKET, (uint8_t *)pDHCPMSG, len, svr_addr, &svr_port); +   #ifdef _DHCP_DEBUG_    +      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); +   #endif    +   } +   else return 0; +	if (svr_port == DHCP_SERVER_PORT) { +      // compare mac address +		if ( (pDHCPMSG->chaddr[0] != DHCP_CHADDR[0]) || (pDHCPMSG->chaddr[1] != DHCP_CHADDR[1]) || +		     (pDHCPMSG->chaddr[2] != DHCP_CHADDR[2]) || (pDHCPMSG->chaddr[3] != DHCP_CHADDR[3]) || +		     (pDHCPMSG->chaddr[4] != DHCP_CHADDR[4]) || (pDHCPMSG->chaddr[5] != DHCP_CHADDR[5])   ) +         return 0; +      type = 0; +		p = (uint8_t *)(&pDHCPMSG->op); +		p = p + 240;      // 240 = sizeof(RIP_MSG) + MAGIC_COOKIE size in RIP_MSG.opt - sizeof(RIP_MSG.opt) +		e = p + (len - 240); + +		while ( p < e ) { + +			switch ( *p ) { + +   			case endOption : +   			   p = e;   // for break while(p < e) +   				break; +            case padOption : +   				p++; +   				break; +   			case dhcpMessageType : +   				p++; +   				p++; +   				type = *p++; +   				break; +   			case subnetMask : +   				p++; +   				p++; +   				DHCP_allocated_sn[0] = *p++; +   				DHCP_allocated_sn[1] = *p++; +   				DHCP_allocated_sn[2] = *p++; +   				DHCP_allocated_sn[3] = *p++; +   				break; +   			case routersOnSubnet : +   				p++; +   				opt_len = *p++;        +   				DHCP_allocated_gw[0] = *p++; +   				DHCP_allocated_gw[1] = *p++; +   				DHCP_allocated_gw[2] = *p++; +   				DHCP_allocated_gw[3] = *p++; +   				p = p + (opt_len - 4); +   				break; +   			case dns : +   				p++;                   +   				opt_len = *p++;        +   				DHCP_allocated_dns[0] = *p++; +   				DHCP_allocated_dns[1] = *p++; +   				DHCP_allocated_dns[2] = *p++; +   				DHCP_allocated_dns[3] = *p++; +   				p = p + (opt_len - 4); +   				break; +   			case dhcpIPaddrLeaseTime : +   				p++; +   				opt_len = *p++; +   				dhcp_lease_time  = *p++; +   				dhcp_lease_time  = (dhcp_lease_time << 8) + *p++; +   				dhcp_lease_time  = (dhcp_lease_time << 8) + *p++; +   				dhcp_lease_time  = (dhcp_lease_time << 8) + *p++; +            #ifdef _DHCP_DEBUG_   +                dhcp_lease_time = 10; + 			#endif +   				break; +   			case dhcpServerIdentifier : +   				p++; +   				opt_len = *p++; +   				DHCP_SIP[0] = *p++; +   				DHCP_SIP[1] = *p++; +   				DHCP_SIP[2] = *p++; +   				DHCP_SIP[3] = *p++; +   				break; +   			default : +   				p++; +   				opt_len = *p++; +   				p += opt_len; +   				break; +			} // switch +		} // while +	} // if +	return	type; +} + +uint8_t DHCP_run(void) +{ +	uint8_t  type; +	uint8_t  ret; + +	if(dhcp_state == STATE_DHCP_STOP) return DHCP_STOPPED; + +	if(getSn_SR(DHCP_SOCKET) != SOCK_UDP) +	   socket(DHCP_SOCKET, Sn_MR_UDP, DHCP_CLIENT_PORT, 0x00); + +	ret = DHCP_RUNNING; +	type = parseDHCPMSG(); + +	switch ( dhcp_state ) { +	   case STATE_DHCP_INIT     : +         DHCP_allocated_ip[0] = 0; +         DHCP_allocated_ip[1] = 0; +         DHCP_allocated_ip[2] = 0; +         DHCP_allocated_ip[3] = 0; +   		send_DHCP_DISCOVER(); +   		dhcp_state = STATE_DHCP_DISCOVER; +   		break; +		case STATE_DHCP_DISCOVER : +			if (type == DHCP_OFFER){ +#ifdef _DHCP_DEBUG_ +				printf("> Receive DHCP_OFFER\r\n"); +#endif +            DHCP_allocated_ip[0] = pDHCPMSG->yiaddr[0]; +            DHCP_allocated_ip[1] = pDHCPMSG->yiaddr[1]; +            DHCP_allocated_ip[2] = pDHCPMSG->yiaddr[2]; +            DHCP_allocated_ip[3] = pDHCPMSG->yiaddr[3]; + +				send_DHCP_REQUEST(); +				dhcp_state = STATE_DHCP_REQUEST; +			} else ret = check_DHCP_timeout(); +         break; + +		case STATE_DHCP_REQUEST : +			if (type == DHCP_ACK) { + +#ifdef _DHCP_DEBUG_ +				printf("> Receive DHCP_ACK\r\n"); +#endif +				if (check_DHCP_leasedIP()) { +					// Network info assignment from DHCP +					dhcp_ip_assign(); +					reset_DHCP_timeout(); + +					dhcp_state = STATE_DHCP_LEASED; +				} else { +					// IP address conflict occurred +					reset_DHCP_timeout(); +					dhcp_ip_conflict(); +				    dhcp_state = STATE_DHCP_INIT; +				} +			} else if (type == DHCP_NAK) { + +#ifdef _DHCP_DEBUG_ +				printf("> Receive DHCP_NACK\r\n"); +#endif + +				reset_DHCP_timeout(); + +				dhcp_state = STATE_DHCP_DISCOVER; +			} else ret = check_DHCP_timeout(); +		break; + +		case STATE_DHCP_LEASED : +		   ret = DHCP_IP_LEASED; +			if ((dhcp_lease_time != INFINITE_LEASETIME) && ((dhcp_lease_time/2) < dhcp_tick_1s)) { +				 +#ifdef _DHCP_DEBUG_ + 				printf("> Maintains the IP address \r\n"); +#endif + +				type = 0; +				OLD_allocated_ip[0] = DHCP_allocated_ip[0]; +				OLD_allocated_ip[1] = DHCP_allocated_ip[1]; +				OLD_allocated_ip[2] = DHCP_allocated_ip[2]; +				OLD_allocated_ip[3] = DHCP_allocated_ip[3]; +				 +				DHCP_XID++; + +				send_DHCP_REQUEST(); + +				reset_DHCP_timeout(); + +				dhcp_state = STATE_DHCP_REREQUEST; +			} +		break; + +		case STATE_DHCP_REREQUEST : +		   ret = DHCP_IP_LEASED; +			if (type == DHCP_ACK) { +				dhcp_retry_count = 0; +				if (OLD_allocated_ip[0] != DHCP_allocated_ip[0] ||  +				    OLD_allocated_ip[1] != DHCP_allocated_ip[1] || +				    OLD_allocated_ip[2] != DHCP_allocated_ip[2] || +				    OLD_allocated_ip[3] != DHCP_allocated_ip[3])  +				{ +					ret = DHCP_IP_CHANGED; +					dhcp_ip_update(); +               #ifdef _DHCP_DEBUG_ +                  printf(">IP changed.\r\n"); +               #endif +					 +				} +         #ifdef _DHCP_DEBUG_ +            else printf(">IP is continued.\r\n"); +         #endif            				 +				reset_DHCP_timeout(); +				dhcp_state = STATE_DHCP_LEASED; +			} else if (type == DHCP_NAK) { + +#ifdef _DHCP_DEBUG_ +				printf("> Receive DHCP_NACK, Failed to maintain ip\r\n"); +#endif + +				reset_DHCP_timeout(); + +				dhcp_state = STATE_DHCP_DISCOVER; +			} else ret = check_DHCP_timeout(); +	   	break; +		default : +   		break; +	} + +	return ret; +} + +void    DHCP_stop(void) +{ +   close(DHCP_SOCKET); +   dhcp_state = STATE_DHCP_STOP; +} + +uint8_t check_DHCP_timeout(void) +{ +	uint8_t ret = DHCP_RUNNING; +	 +	if (dhcp_retry_count < MAX_DHCP_RETRY) { +		if (dhcp_tick_next < dhcp_tick_1s) { + +			switch ( dhcp_state ) { +				case STATE_DHCP_DISCOVER : +//					printf("<<timeout>> state : STATE_DHCP_DISCOVER\r\n"); +					send_DHCP_DISCOVER(); +				break; +		 +				case STATE_DHCP_REQUEST : +//					printf("<<timeout>> state : STATE_DHCP_REQUEST\r\n"); + +					send_DHCP_REQUEST(); +				break; + +				case STATE_DHCP_REREQUEST : +//					printf("<<timeout>> state : STATE_DHCP_REREQUEST\r\n"); +					 +					send_DHCP_REQUEST(); +				break; +		 +				default : +				break; +			} + +			dhcp_tick_1s = 0; +			dhcp_tick_next = dhcp_tick_1s + DHCP_WAIT_TIME; +			dhcp_retry_count++; +		} +	} else { // timeout occurred + +		switch(dhcp_state) { +			case STATE_DHCP_DISCOVER: +				dhcp_state = STATE_DHCP_INIT; +				ret = DHCP_FAILED; +				break; +			case STATE_DHCP_REQUEST: +			case STATE_DHCP_REREQUEST: +				send_DHCP_DISCOVER(); +				dhcp_state = STATE_DHCP_DISCOVER; +				break; +			default : +				break; +		} +		reset_DHCP_timeout(); +	} +	return ret; +} + +int8_t check_DHCP_leasedIP(void) +{ +	uint8_t tmp; +	int32_t ret; + +	//WIZchip RCR value changed for ARP Timeout count control +	tmp = getRCR(); +	setRCR(0x03); + +	// IP conflict detection : ARP request - ARP reply +	// Broadcasting ARP Request for check the IP conflict using UDP sendto() function +	ret = sendto(DHCP_SOCKET, (uint8_t *)"CHECK_IP_CONFLICT", 17, DHCP_allocated_ip, 5000); + +	// RCR value restore +	setRCR(tmp); + +	if(ret == SOCKERR_TIMEOUT) { +		// UDP send Timeout occurred : allocated IP address is unique, DHCP Success + +#ifdef _DHCP_DEBUG_ +		printf("\r\n> Check leased IP - OK\r\n"); +#endif + +		return 1; +	} else { +		// Received ARP reply or etc : IP address conflict occur, DHCP Failed +		send_DHCP_DECLINE(); + +		ret = dhcp_tick_1s; +		while((dhcp_tick_1s - ret) < 2) ;   // wait for 1s over; wait to complete to send DECLINE message; + +		return 0; +	} +}	 + +void DHCP_init(uint8_t s, uint8_t * buf) +{ +   uint8_t zeroip[4] = {0,0,0,0}; +   getSHAR(DHCP_CHADDR); +   if((DHCP_CHADDR[0] | DHCP_CHADDR[1]  | DHCP_CHADDR[2] | DHCP_CHADDR[3] | DHCP_CHADDR[4] | DHCP_CHADDR[5]) == 0x00) +   { +      // assign temporary mac address, you should be set SHAR before call this function. +      DHCP_CHADDR[0] = 0x00; +      DHCP_CHADDR[1] = 0x08; +      DHCP_CHADDR[2] = 0xdc;       +      DHCP_CHADDR[3] = 0x00; +      DHCP_CHADDR[4] = 0x00; +      DHCP_CHADDR[5] = 0x00;  +      setSHAR(DHCP_CHADDR);      +   } + +	DHCP_SOCKET = s; // SOCK_DHCP +	pDHCPMSG = (RIP_MSG*)buf; +	DHCP_XID = 0x12345678; + +	// WIZchip Netinfo Clear +	setSIPR(zeroip); +	setSIPR(zeroip); +	setGAR(zeroip); + +	reset_DHCP_timeout(); +	dhcp_state = STATE_DHCP_INIT; +} + + +/* Rset the DHCP timeout count and retry count. */ +void reset_DHCP_timeout(void) +{ +	dhcp_tick_1s = 0; +	dhcp_tick_next = DHCP_WAIT_TIME; +	dhcp_retry_count = 0; +} + +void DHCP_time_handler(void) +{ +	dhcp_tick_1s++; +} + +void getIPfromDHCP(uint8_t* ip) +{ +	ip[0] = DHCP_allocated_ip[0]; +	ip[1] = DHCP_allocated_ip[1]; +	ip[2] = DHCP_allocated_ip[2];	 +	ip[3] = DHCP_allocated_ip[3]; +} + +void getGWfromDHCP(uint8_t* ip) +{ +	ip[0] =DHCP_allocated_gw[0]; +	ip[1] =DHCP_allocated_gw[1]; +	ip[2] =DHCP_allocated_gw[2]; +	ip[3] =DHCP_allocated_gw[3];			 +} + +void getSNfromDHCP(uint8_t* ip) +{ +   ip[0] = DHCP_allocated_sn[0]; +   ip[1] = DHCP_allocated_sn[1]; +   ip[2] = DHCP_allocated_sn[2]; +   ip[3] = DHCP_allocated_sn[3];          +} + +void getDNSfromDHCP(uint8_t* ip) +{ +   ip[0] = DHCP_allocated_dns[0]; +   ip[1] = DHCP_allocated_dns[1]; +   ip[2] = DHCP_allocated_dns[2]; +   ip[3] = DHCP_allocated_dns[3];          +} + +uint32_t getDHCPLeasetime(void) +{ +	return dhcp_lease_time; +} + + + + | 
