| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007 |
- //*****************************************************************************
- //
- //! \file dhcp.c
- //! \brief DHCP APIs implement file.
- //! \details Processing DHCP protocol as DISCOVER, OFFER, REQUEST, ACK, NACK and DECLINE.
- //! \version 1.1.1
- //! \date 2019/10/08
- //! \par Revision history
- //! <2019/10/08> compare DHCP server ip address
- //! <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 "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
- uint8_t DHCP_REAL_SIP[4]; // For extract my DHCP server in a few DHCP server
- // 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));
- char NibbleToHex(uint8_t nibble);
-
- /* 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);
- /* Initialize 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();
- DHCP_SIP[0]=0;
- DHCP_SIP[1]=0;
- DHCP_SIP[2]=0;
- DHCP_SIP[3]=0;
- DHCP_REAL_SIP[0]=0;
- DHCP_REAL_SIP[1]=0;
- DHCP_REAL_SIP[2]=0;
- DHCP_REAL_SIP[3]=0;
- 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++] = NibbleToHex(DHCP_CHADDR[3] >> 4);
- pDHCPMSG->OPT[k++] = NibbleToHex(DHCP_CHADDR[3]);
- pDHCPMSG->OPT[k++] = NibbleToHex(DHCP_CHADDR[4] >> 4);
- pDHCPMSG->OPT[k++] = NibbleToHex(DHCP_CHADDR[4]);
- pDHCPMSG->OPT[k++] = NibbleToHex(DHCP_CHADDR[5] >> 4);
- pDHCPMSG->OPT[k++] = NibbleToHex(DHCP_CHADDR[5]);
- pDHCPMSG->OPT[k - (i+6+1)] = i+6; // 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++] = NibbleToHex(DHCP_CHADDR[3] >> 4);
- pDHCPMSG->OPT[k++] = NibbleToHex(DHCP_CHADDR[3]);
- pDHCPMSG->OPT[k++] = NibbleToHex(DHCP_CHADDR[4] >> 4);
- pDHCPMSG->OPT[k++] = NibbleToHex(DHCP_CHADDR[4]);
- pDHCPMSG->OPT[k++] = NibbleToHex(DHCP_CHADDR[5] >> 4);
- pDHCPMSG->OPT[k++] = NibbleToHex(DHCP_CHADDR[5]);
- pDHCPMSG->OPT[k - (i+6+1)] = i+6; // 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 = 0;
- 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]) )
- {
- #ifdef _DHCP_DEBUG_
- printf("No My DHCP Message. This message is ignored.\r\n");
- #endif
- return 0;
- }
- //compare DHCP server ip address
- if((DHCP_SIP[0]!=0) || (DHCP_SIP[1]!=0) || (DHCP_SIP[2]!=0) || (DHCP_SIP[3]!=0)){
- 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])) &&
- ((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])) )
- {
- #ifdef _DHCP_DEBUG_
- printf("Another DHCP sever send a response message. This is ignored.\r\n");
- #endif
- return 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++;
- DHCP_REAL_SIP[0]=svr_addr[0];
- DHCP_REAL_SIP[1]=svr_addr[1];
- DHCP_REAL_SIP[2]=svr_addr[2];
- DHCP_REAL_SIP[3]=svr_addr[3];
- 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)
- {
- // assigning 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;
- {
- DHCP_XID += DHCP_CHADDR[3];
- DHCP_XID += DHCP_CHADDR[4];
- DHCP_XID += DHCP_CHADDR[5];
- DHCP_XID += (DHCP_CHADDR[3] ^ DHCP_CHADDR[4] ^ DHCP_CHADDR[5]);
- }
- // WIZchip Netinfo Clear
- setSIPR(zeroip);
- setGAR(zeroip);
- reset_DHCP_timeout();
- dhcp_state = STATE_DHCP_INIT;
- }
- /* Reset 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;
- }
- char NibbleToHex(uint8_t nibble)
- {
- nibble &= 0x0F;
- if (nibble <= 9)
- return nibble + '0';
- else
- return nibble + ('A'-0x0A);
- }
|