dhcp.c 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007
  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. #include "socket.h"
  53. #include "dhcp.h"
  54. /* If you want to display debug & processing message, Define _DHCP_DEBUG_ in dhcp.h */
  55. #ifdef _DHCP_DEBUG_
  56. #include <stdio.h>
  57. #endif
  58. /* DHCP state machine. */
  59. #define STATE_DHCP_INIT 0 ///< Initialize
  60. #define STATE_DHCP_DISCOVER 1 ///< send DISCOVER and wait OFFER
  61. #define STATE_DHCP_REQUEST 2 ///< send REQEUST and wait ACK or NACK
  62. #define STATE_DHCP_LEASED 3 ///< ReceiveD ACK and IP leased
  63. #define STATE_DHCP_REREQUEST 4 ///< send REQUEST for maintaining leased IP
  64. #define STATE_DHCP_RELEASE 5 ///< No use
  65. #define STATE_DHCP_STOP 6 ///< Stop processing DHCP
  66. #define DHCP_FLAGSBROADCAST 0x8000 ///< The broadcast value of flags in @ref RIP_MSG
  67. #define DHCP_FLAGSUNICAST 0x0000 ///< The unicast value of flags in @ref RIP_MSG
  68. /* DHCP message OP code */
  69. #define DHCP_BOOTREQUEST 1 ///< Request Message used in op of @ref RIP_MSG
  70. #define DHCP_BOOTREPLY 2 ///< Reply Message used i op of @ref RIP_MSG
  71. /* DHCP message type */
  72. #define DHCP_DISCOVER 1 ///< DISCOVER message in OPT of @ref RIP_MSG
  73. #define DHCP_OFFER 2 ///< OFFER message in OPT of @ref RIP_MSG
  74. #define DHCP_REQUEST 3 ///< REQUEST message in OPT of @ref RIP_MSG
  75. #define DHCP_DECLINE 4 ///< DECLINE message in OPT of @ref RIP_MSG
  76. #define DHCP_ACK 5 ///< ACK message in OPT of @ref RIP_MSG
  77. #define DHCP_NAK 6 ///< NACK message in OPT of @ref RIP_MSG
  78. #define DHCP_RELEASE 7 ///< RELEASE message in OPT of @ref RIP_MSG. No use
  79. #define DHCP_INFORM 8 ///< INFORM message in OPT of @ref RIP_MSG. No use
  80. #define DHCP_HTYPE10MB 1 ///< Used in type of @ref RIP_MSG
  81. #define DHCP_HTYPE100MB 2 ///< Used in type of @ref RIP_MSG
  82. #define DHCP_HLENETHERNET 6 ///< Used in hlen of @ref RIP_MSG
  83. #define DHCP_HOPS 0 ///< Used in hops of @ref RIP_MSG
  84. #define DHCP_SECS 0 ///< Used in secs of @ref RIP_MSG
  85. #define INFINITE_LEASETIME 0xffffffff ///< Infinite lease time
  86. #define OPT_SIZE 312 /// Max OPT size of @ref RIP_MSG
  87. #define RIP_MSG_SIZE (236+OPT_SIZE) /// Max size of @ref RIP_MSG
  88. /*
  89. * @brief DHCP option and value (cf. RFC1533)
  90. */
  91. enum
  92. {
  93. padOption = 0,
  94. subnetMask = 1,
  95. timerOffset = 2,
  96. routersOnSubnet = 3,
  97. timeServer = 4,
  98. nameServer = 5,
  99. dns = 6,
  100. logServer = 7,
  101. cookieServer = 8,
  102. lprServer = 9,
  103. impressServer = 10,
  104. resourceLocationServer = 11,
  105. hostName = 12,
  106. bootFileSize = 13,
  107. meritDumpFile = 14,
  108. domainName = 15,
  109. swapServer = 16,
  110. rootPath = 17,
  111. extentionsPath = 18,
  112. IPforwarding = 19,
  113. nonLocalSourceRouting = 20,
  114. policyFilter = 21,
  115. maxDgramReasmSize = 22,
  116. defaultIPTTL = 23,
  117. pathMTUagingTimeout = 24,
  118. pathMTUplateauTable = 25,
  119. ifMTU = 26,
  120. allSubnetsLocal = 27,
  121. broadcastAddr = 28,
  122. performMaskDiscovery = 29,
  123. maskSupplier = 30,
  124. performRouterDiscovery = 31,
  125. routerSolicitationAddr = 32,
  126. staticRoute = 33,
  127. trailerEncapsulation = 34,
  128. arpCacheTimeout = 35,
  129. ethernetEncapsulation = 36,
  130. tcpDefaultTTL = 37,
  131. tcpKeepaliveInterval = 38,
  132. tcpKeepaliveGarbage = 39,
  133. nisDomainName = 40,
  134. nisServers = 41,
  135. ntpServers = 42,
  136. vendorSpecificInfo = 43,
  137. netBIOSnameServer = 44,
  138. netBIOSdgramDistServer = 45,
  139. netBIOSnodeType = 46,
  140. netBIOSscope = 47,
  141. xFontServer = 48,
  142. xDisplayManager = 49,
  143. dhcpRequestedIPaddr = 50,
  144. dhcpIPaddrLeaseTime = 51,
  145. dhcpOptionOverload = 52,
  146. dhcpMessageType = 53,
  147. dhcpServerIdentifier = 54,
  148. dhcpParamRequest = 55,
  149. dhcpMsg = 56,
  150. dhcpMaxMsgSize = 57,
  151. dhcpT1value = 58,
  152. dhcpT2value = 59,
  153. dhcpClassIdentifier = 60,
  154. dhcpClientIdentifier = 61,
  155. endOption = 255
  156. };
  157. /*
  158. * @brief DHCP message format
  159. */
  160. typedef struct {
  161. uint8_t op; ///< @ref DHCP_BOOTREQUEST or @ref DHCP_BOOTREPLY
  162. uint8_t htype; ///< @ref DHCP_HTYPE10MB or @ref DHCP_HTYPE100MB
  163. uint8_t hlen; ///< @ref DHCP_HLENETHERNET
  164. uint8_t hops; ///< @ref DHCP_HOPS
  165. uint32_t xid; ///< @ref DHCP_XID This increase one every DHCP transaction.
  166. uint16_t secs; ///< @ref DHCP_SECS
  167. uint16_t flags; ///< @ref DHCP_FLAGSBROADCAST or @ref DHCP_FLAGSUNICAST
  168. uint8_t ciaddr[4]; ///< @ref Request IP to DHCP sever
  169. uint8_t yiaddr[4]; ///< @ref Offered IP from DHCP server
  170. uint8_t siaddr[4]; ///< No use
  171. uint8_t giaddr[4]; ///< No use
  172. uint8_t chaddr[16]; ///< DHCP client 6bytes MAC address. Others is filled to zero
  173. uint8_t sname[64]; ///< No use
  174. uint8_t file[128]; ///< No use
  175. uint8_t OPT[OPT_SIZE]; ///< Option
  176. } RIP_MSG;
  177. uint8_t DHCP_SOCKET; // Socket number for DHCP
  178. uint8_t DHCP_SIP[4]; // DHCP Server IP address
  179. uint8_t DHCP_REAL_SIP[4]; // For extract my DHCP server in a few DHCP server
  180. // Network information from DHCP Server
  181. uint8_t OLD_allocated_ip[4] = {0, }; // Previous IP address
  182. uint8_t DHCP_allocated_ip[4] = {0, }; // IP address from DHCP
  183. uint8_t DHCP_allocated_gw[4] = {0, }; // Gateway address from DHCP
  184. uint8_t DHCP_allocated_sn[4] = {0, }; // Subnet mask from DHCP
  185. uint8_t DHCP_allocated_dns[4] = {0, }; // DNS address from DHCP
  186. int8_t dhcp_state = STATE_DHCP_INIT; // DHCP state
  187. int8_t dhcp_retry_count = 0;
  188. uint32_t dhcp_lease_time = INFINITE_LEASETIME;
  189. volatile uint32_t dhcp_tick_1s = 0; // unit 1 second
  190. uint32_t dhcp_tick_next = DHCP_WAIT_TIME ;
  191. uint32_t DHCP_XID; // Any number
  192. RIP_MSG* pDHCPMSG; // Buffer pointer for DHCP processing
  193. uint8_t HOST_NAME[] = DCHP_HOST_NAME;
  194. uint8_t DHCP_CHADDR[6]; // DHCP Client MAC address.
  195. /* The default callback function */
  196. void default_ip_assign(void);
  197. void default_ip_update(void);
  198. void default_ip_conflict(void);
  199. /* Callback handler */
  200. void (*dhcp_ip_assign)(void) = default_ip_assign; /* handler to be called when the IP address from DHCP server is first assigned */
  201. void (*dhcp_ip_update)(void) = default_ip_update; /* handler to be called when the IP address from DHCP server is updated */
  202. void (*dhcp_ip_conflict)(void) = default_ip_conflict; /* handler to be called when the IP address from DHCP server is conflict */
  203. void reg_dhcp_cbfunc(void(*ip_assign)(void), void(*ip_update)(void), void(*ip_conflict)(void));
  204. char NibbleToHex(uint8_t nibble);
  205. /* send DISCOVER message to DHCP server */
  206. void send_DHCP_DISCOVER(void);
  207. /* send REQEUST message to DHCP server */
  208. void send_DHCP_REQUEST(void);
  209. /* send DECLINE message to DHCP server */
  210. void send_DHCP_DECLINE(void);
  211. /* IP conflict check by sending ARP-request to leased IP and wait ARP-response. */
  212. int8_t check_DHCP_leasedIP(void);
  213. /* check the timeout in DHCP process */
  214. uint8_t check_DHCP_timeout(void);
  215. /* Initialize to timeout process. */
  216. void reset_DHCP_timeout(void);
  217. /* Parse message as OFFER and ACK and NACK from DHCP server.*/
  218. int8_t parseDHCPCMSG(void);
  219. /* The default handler of ip assign first */
  220. void default_ip_assign(void)
  221. {
  222. setSIPR(DHCP_allocated_ip);
  223. setSUBR(DHCP_allocated_sn);
  224. setGAR (DHCP_allocated_gw);
  225. }
  226. /* The default handler of ip changed */
  227. void default_ip_update(void)
  228. {
  229. /* WIZchip Software Reset */
  230. setMR(MR_RST);
  231. getMR(); // for delay
  232. default_ip_assign();
  233. setSHAR(DHCP_CHADDR);
  234. }
  235. /* The default handler of ip changed */
  236. void default_ip_conflict(void)
  237. {
  238. // WIZchip Software Reset
  239. setMR(MR_RST);
  240. getMR(); // for delay
  241. setSHAR(DHCP_CHADDR);
  242. }
  243. /* register the call back func. */
  244. void reg_dhcp_cbfunc(void(*ip_assign)(void), void(*ip_update)(void), void(*ip_conflict)(void))
  245. {
  246. dhcp_ip_assign = default_ip_assign;
  247. dhcp_ip_update = default_ip_update;
  248. dhcp_ip_conflict = default_ip_conflict;
  249. if(ip_assign) dhcp_ip_assign = ip_assign;
  250. if(ip_update) dhcp_ip_update = ip_update;
  251. if(ip_conflict) dhcp_ip_conflict = ip_conflict;
  252. }
  253. /* make the common DHCP message */
  254. void makeDHCPMSG(void)
  255. {
  256. uint8_t bk_mac[6];
  257. uint8_t* ptmp;
  258. uint8_t i;
  259. getSHAR(bk_mac);
  260. pDHCPMSG->op = DHCP_BOOTREQUEST;
  261. pDHCPMSG->htype = DHCP_HTYPE10MB;
  262. pDHCPMSG->hlen = DHCP_HLENETHERNET;
  263. pDHCPMSG->hops = DHCP_HOPS;
  264. ptmp = (uint8_t*)(&pDHCPMSG->xid);
  265. *(ptmp+0) = (uint8_t)((DHCP_XID & 0xFF000000) >> 24);
  266. *(ptmp+1) = (uint8_t)((DHCP_XID & 0x00FF0000) >> 16);
  267. *(ptmp+2) = (uint8_t)((DHCP_XID & 0x0000FF00) >> 8);
  268. *(ptmp+3) = (uint8_t)((DHCP_XID & 0x000000FF) >> 0);
  269. pDHCPMSG->secs = DHCP_SECS;
  270. ptmp = (uint8_t*)(&pDHCPMSG->flags);
  271. *(ptmp+0) = (uint8_t)((DHCP_FLAGSBROADCAST & 0xFF00) >> 8);
  272. *(ptmp+1) = (uint8_t)((DHCP_FLAGSBROADCAST & 0x00FF) >> 0);
  273. pDHCPMSG->ciaddr[0] = 0;
  274. pDHCPMSG->ciaddr[1] = 0;
  275. pDHCPMSG->ciaddr[2] = 0;
  276. pDHCPMSG->ciaddr[3] = 0;
  277. pDHCPMSG->yiaddr[0] = 0;
  278. pDHCPMSG->yiaddr[1] = 0;
  279. pDHCPMSG->yiaddr[2] = 0;
  280. pDHCPMSG->yiaddr[3] = 0;
  281. pDHCPMSG->siaddr[0] = 0;
  282. pDHCPMSG->siaddr[1] = 0;
  283. pDHCPMSG->siaddr[2] = 0;
  284. pDHCPMSG->siaddr[3] = 0;
  285. pDHCPMSG->giaddr[0] = 0;
  286. pDHCPMSG->giaddr[1] = 0;
  287. pDHCPMSG->giaddr[2] = 0;
  288. pDHCPMSG->giaddr[3] = 0;
  289. pDHCPMSG->chaddr[0] = DHCP_CHADDR[0];
  290. pDHCPMSG->chaddr[1] = DHCP_CHADDR[1];
  291. pDHCPMSG->chaddr[2] = DHCP_CHADDR[2];
  292. pDHCPMSG->chaddr[3] = DHCP_CHADDR[3];
  293. pDHCPMSG->chaddr[4] = DHCP_CHADDR[4];
  294. pDHCPMSG->chaddr[5] = DHCP_CHADDR[5];
  295. for (i = 6; i < 16; i++) pDHCPMSG->chaddr[i] = 0;
  296. for (i = 0; i < 64; i++) pDHCPMSG->sname[i] = 0;
  297. for (i = 0; i < 128; i++) pDHCPMSG->file[i] = 0;
  298. // MAGIC_COOKIE
  299. pDHCPMSG->OPT[0] = (uint8_t)((MAGIC_COOKIE & 0xFF000000) >> 24);
  300. pDHCPMSG->OPT[1] = (uint8_t)((MAGIC_COOKIE & 0x00FF0000) >> 16);
  301. pDHCPMSG->OPT[2] = (uint8_t)((MAGIC_COOKIE & 0x0000FF00) >> 8);
  302. pDHCPMSG->OPT[3] = (uint8_t) (MAGIC_COOKIE & 0x000000FF) >> 0;
  303. }
  304. /* SEND DHCP DISCOVER */
  305. void send_DHCP_DISCOVER(void)
  306. {
  307. uint16_t i;
  308. uint8_t ip[4];
  309. uint16_t k = 0;
  310. makeDHCPMSG();
  311. DHCP_SIP[0]=0;
  312. DHCP_SIP[1]=0;
  313. DHCP_SIP[2]=0;
  314. DHCP_SIP[3]=0;
  315. DHCP_REAL_SIP[0]=0;
  316. DHCP_REAL_SIP[1]=0;
  317. DHCP_REAL_SIP[2]=0;
  318. DHCP_REAL_SIP[3]=0;
  319. k = 4; // because MAGIC_COOKIE already made by makeDHCPMSG()
  320. // Option Request Param
  321. pDHCPMSG->OPT[k++] = dhcpMessageType;
  322. pDHCPMSG->OPT[k++] = 0x01;
  323. pDHCPMSG->OPT[k++] = DHCP_DISCOVER;
  324. // Client identifier
  325. pDHCPMSG->OPT[k++] = dhcpClientIdentifier;
  326. pDHCPMSG->OPT[k++] = 0x07;
  327. pDHCPMSG->OPT[k++] = 0x01;
  328. pDHCPMSG->OPT[k++] = DHCP_CHADDR[0];
  329. pDHCPMSG->OPT[k++] = DHCP_CHADDR[1];
  330. pDHCPMSG->OPT[k++] = DHCP_CHADDR[2];
  331. pDHCPMSG->OPT[k++] = DHCP_CHADDR[3];
  332. pDHCPMSG->OPT[k++] = DHCP_CHADDR[4];
  333. pDHCPMSG->OPT[k++] = DHCP_CHADDR[5];
  334. // host name
  335. pDHCPMSG->OPT[k++] = hostName;
  336. pDHCPMSG->OPT[k++] = 0; // fill zero length of hostname
  337. for(i = 0 ; HOST_NAME[i] != 0; i++)
  338. pDHCPMSG->OPT[k++] = HOST_NAME[i];
  339. pDHCPMSG->OPT[k++] = NibbleToHex(DHCP_CHADDR[3] >> 4);
  340. pDHCPMSG->OPT[k++] = NibbleToHex(DHCP_CHADDR[3]);
  341. pDHCPMSG->OPT[k++] = NibbleToHex(DHCP_CHADDR[4] >> 4);
  342. pDHCPMSG->OPT[k++] = NibbleToHex(DHCP_CHADDR[4]);
  343. pDHCPMSG->OPT[k++] = NibbleToHex(DHCP_CHADDR[5] >> 4);
  344. pDHCPMSG->OPT[k++] = NibbleToHex(DHCP_CHADDR[5]);
  345. pDHCPMSG->OPT[k - (i+6+1)] = i+6; // length of hostname
  346. pDHCPMSG->OPT[k++] = dhcpParamRequest;
  347. pDHCPMSG->OPT[k++] = 0x06; // length of request
  348. pDHCPMSG->OPT[k++] = subnetMask;
  349. pDHCPMSG->OPT[k++] = routersOnSubnet;
  350. pDHCPMSG->OPT[k++] = dns;
  351. pDHCPMSG->OPT[k++] = domainName;
  352. pDHCPMSG->OPT[k++] = dhcpT1value;
  353. pDHCPMSG->OPT[k++] = dhcpT2value;
  354. pDHCPMSG->OPT[k++] = endOption;
  355. for (i = k; i < OPT_SIZE; i++) pDHCPMSG->OPT[i] = 0;
  356. // send broadcasting packet
  357. ip[0] = 255;
  358. ip[1] = 255;
  359. ip[2] = 255;
  360. ip[3] = 255;
  361. #ifdef _DHCP_DEBUG_
  362. printf("> Send DHCP_DISCOVER\r\n");
  363. #endif
  364. sendto(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT);
  365. }
  366. /* SEND DHCP REQUEST */
  367. void send_DHCP_REQUEST(void)
  368. {
  369. int i;
  370. uint8_t ip[4];
  371. uint16_t k = 0;
  372. makeDHCPMSG();
  373. if(dhcp_state == STATE_DHCP_LEASED || dhcp_state == STATE_DHCP_REREQUEST)
  374. {
  375. *((uint8_t*)(&pDHCPMSG->flags)) = ((DHCP_FLAGSUNICAST & 0xFF00)>> 8);
  376. *((uint8_t*)(&pDHCPMSG->flags)+1) = (DHCP_FLAGSUNICAST & 0x00FF);
  377. pDHCPMSG->ciaddr[0] = DHCP_allocated_ip[0];
  378. pDHCPMSG->ciaddr[1] = DHCP_allocated_ip[1];
  379. pDHCPMSG->ciaddr[2] = DHCP_allocated_ip[2];
  380. pDHCPMSG->ciaddr[3] = DHCP_allocated_ip[3];
  381. ip[0] = DHCP_SIP[0];
  382. ip[1] = DHCP_SIP[1];
  383. ip[2] = DHCP_SIP[2];
  384. ip[3] = DHCP_SIP[3];
  385. }
  386. else
  387. {
  388. ip[0] = 255;
  389. ip[1] = 255;
  390. ip[2] = 255;
  391. ip[3] = 255;
  392. }
  393. k = 4; // because MAGIC_COOKIE already made by makeDHCPMSG()
  394. // Option Request Param.
  395. pDHCPMSG->OPT[k++] = dhcpMessageType;
  396. pDHCPMSG->OPT[k++] = 0x01;
  397. pDHCPMSG->OPT[k++] = DHCP_REQUEST;
  398. pDHCPMSG->OPT[k++] = dhcpClientIdentifier;
  399. pDHCPMSG->OPT[k++] = 0x07;
  400. pDHCPMSG->OPT[k++] = 0x01;
  401. pDHCPMSG->OPT[k++] = DHCP_CHADDR[0];
  402. pDHCPMSG->OPT[k++] = DHCP_CHADDR[1];
  403. pDHCPMSG->OPT[k++] = DHCP_CHADDR[2];
  404. pDHCPMSG->OPT[k++] = DHCP_CHADDR[3];
  405. pDHCPMSG->OPT[k++] = DHCP_CHADDR[4];
  406. pDHCPMSG->OPT[k++] = DHCP_CHADDR[5];
  407. if(ip[3] == 255) // if(dchp_state == STATE_DHCP_LEASED || dchp_state == DHCP_REREQUEST_STATE)
  408. {
  409. pDHCPMSG->OPT[k++] = dhcpRequestedIPaddr;
  410. pDHCPMSG->OPT[k++] = 0x04;
  411. pDHCPMSG->OPT[k++] = DHCP_allocated_ip[0];
  412. pDHCPMSG->OPT[k++] = DHCP_allocated_ip[1];
  413. pDHCPMSG->OPT[k++] = DHCP_allocated_ip[2];
  414. pDHCPMSG->OPT[k++] = DHCP_allocated_ip[3];
  415. pDHCPMSG->OPT[k++] = dhcpServerIdentifier;
  416. pDHCPMSG->OPT[k++] = 0x04;
  417. pDHCPMSG->OPT[k++] = DHCP_SIP[0];
  418. pDHCPMSG->OPT[k++] = DHCP_SIP[1];
  419. pDHCPMSG->OPT[k++] = DHCP_SIP[2];
  420. pDHCPMSG->OPT[k++] = DHCP_SIP[3];
  421. }
  422. // host name
  423. pDHCPMSG->OPT[k++] = hostName;
  424. pDHCPMSG->OPT[k++] = 0; // length of hostname
  425. for(i = 0 ; HOST_NAME[i] != 0; i++)
  426. pDHCPMSG->OPT[k++] = HOST_NAME[i];
  427. pDHCPMSG->OPT[k++] = NibbleToHex(DHCP_CHADDR[3] >> 4);
  428. pDHCPMSG->OPT[k++] = NibbleToHex(DHCP_CHADDR[3]);
  429. pDHCPMSG->OPT[k++] = NibbleToHex(DHCP_CHADDR[4] >> 4);
  430. pDHCPMSG->OPT[k++] = NibbleToHex(DHCP_CHADDR[4]);
  431. pDHCPMSG->OPT[k++] = NibbleToHex(DHCP_CHADDR[5] >> 4);
  432. pDHCPMSG->OPT[k++] = NibbleToHex(DHCP_CHADDR[5]);
  433. pDHCPMSG->OPT[k - (i+6+1)] = i+6; // length of hostname
  434. pDHCPMSG->OPT[k++] = dhcpParamRequest;
  435. pDHCPMSG->OPT[k++] = 0x08;
  436. pDHCPMSG->OPT[k++] = subnetMask;
  437. pDHCPMSG->OPT[k++] = routersOnSubnet;
  438. pDHCPMSG->OPT[k++] = dns;
  439. pDHCPMSG->OPT[k++] = domainName;
  440. pDHCPMSG->OPT[k++] = dhcpT1value;
  441. pDHCPMSG->OPT[k++] = dhcpT2value;
  442. pDHCPMSG->OPT[k++] = performRouterDiscovery;
  443. pDHCPMSG->OPT[k++] = staticRoute;
  444. pDHCPMSG->OPT[k++] = endOption;
  445. for (i = k; i < OPT_SIZE; i++) pDHCPMSG->OPT[i] = 0;
  446. #ifdef _DHCP_DEBUG_
  447. printf("> Send DHCP_REQUEST\r\n");
  448. #endif
  449. sendto(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT);
  450. }
  451. /* SEND DHCP DHCPDECLINE */
  452. void send_DHCP_DECLINE(void)
  453. {
  454. int i;
  455. uint8_t ip[4];
  456. uint16_t k = 0;
  457. makeDHCPMSG();
  458. k = 4; // because MAGIC_COOKIE already made by makeDHCPMSG()
  459. *((uint8_t*)(&pDHCPMSG->flags)) = ((DHCP_FLAGSUNICAST & 0xFF00)>> 8);
  460. *((uint8_t*)(&pDHCPMSG->flags)+1) = (DHCP_FLAGSUNICAST & 0x00FF);
  461. // Option Request Param.
  462. pDHCPMSG->OPT[k++] = dhcpMessageType;
  463. pDHCPMSG->OPT[k++] = 0x01;
  464. pDHCPMSG->OPT[k++] = DHCP_DECLINE;
  465. pDHCPMSG->OPT[k++] = dhcpClientIdentifier;
  466. pDHCPMSG->OPT[k++] = 0x07;
  467. pDHCPMSG->OPT[k++] = 0x01;
  468. pDHCPMSG->OPT[k++] = DHCP_CHADDR[0];
  469. pDHCPMSG->OPT[k++] = DHCP_CHADDR[1];
  470. pDHCPMSG->OPT[k++] = DHCP_CHADDR[2];
  471. pDHCPMSG->OPT[k++] = DHCP_CHADDR[3];
  472. pDHCPMSG->OPT[k++] = DHCP_CHADDR[4];
  473. pDHCPMSG->OPT[k++] = DHCP_CHADDR[5];
  474. pDHCPMSG->OPT[k++] = dhcpRequestedIPaddr;
  475. pDHCPMSG->OPT[k++] = 0x04;
  476. pDHCPMSG->OPT[k++] = DHCP_allocated_ip[0];
  477. pDHCPMSG->OPT[k++] = DHCP_allocated_ip[1];
  478. pDHCPMSG->OPT[k++] = DHCP_allocated_ip[2];
  479. pDHCPMSG->OPT[k++] = DHCP_allocated_ip[3];
  480. pDHCPMSG->OPT[k++] = dhcpServerIdentifier;
  481. pDHCPMSG->OPT[k++] = 0x04;
  482. pDHCPMSG->OPT[k++] = DHCP_SIP[0];
  483. pDHCPMSG->OPT[k++] = DHCP_SIP[1];
  484. pDHCPMSG->OPT[k++] = DHCP_SIP[2];
  485. pDHCPMSG->OPT[k++] = DHCP_SIP[3];
  486. pDHCPMSG->OPT[k++] = endOption;
  487. for (i = k; i < OPT_SIZE; i++) pDHCPMSG->OPT[i] = 0;
  488. //send broadcasting packet
  489. ip[0] = 0xFF;
  490. ip[1] = 0xFF;
  491. ip[2] = 0xFF;
  492. ip[3] = 0xFF;
  493. #ifdef _DHCP_DEBUG_
  494. printf("\r\n> Send DHCP_DECLINE\r\n");
  495. #endif
  496. sendto(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT);
  497. }
  498. /* PARSE REPLY pDHCPMSG */
  499. int8_t parseDHCPMSG(void)
  500. {
  501. uint8_t svr_addr[6];
  502. uint16_t svr_port;
  503. uint16_t len;
  504. uint8_t * p;
  505. uint8_t * e;
  506. uint8_t type = 0;
  507. uint8_t opt_len;
  508. if((len = getSn_RX_RSR(DHCP_SOCKET)) > 0)
  509. {
  510. len = recvfrom(DHCP_SOCKET, (uint8_t *)pDHCPMSG, len, svr_addr, &svr_port);
  511. #ifdef _DHCP_DEBUG_
  512. 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);
  513. #endif
  514. }
  515. else return 0;
  516. if (svr_port == DHCP_SERVER_PORT) {
  517. // compare mac address
  518. if ( (pDHCPMSG->chaddr[0] != DHCP_CHADDR[0]) || (pDHCPMSG->chaddr[1] != DHCP_CHADDR[1]) ||
  519. (pDHCPMSG->chaddr[2] != DHCP_CHADDR[2]) || (pDHCPMSG->chaddr[3] != DHCP_CHADDR[3]) ||
  520. (pDHCPMSG->chaddr[4] != DHCP_CHADDR[4]) || (pDHCPMSG->chaddr[5] != DHCP_CHADDR[5]) )
  521. {
  522. #ifdef _DHCP_DEBUG_
  523. printf("No My DHCP Message. This message is ignored.\r\n");
  524. #endif
  525. return 0;
  526. }
  527. //compare DHCP server ip address
  528. if((DHCP_SIP[0]!=0) || (DHCP_SIP[1]!=0) || (DHCP_SIP[2]!=0) || (DHCP_SIP[3]!=0)){
  529. 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])) &&
  530. ((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])) )
  531. {
  532. #ifdef _DHCP_DEBUG_
  533. printf("Another DHCP sever send a response message. This is ignored.\r\n");
  534. #endif
  535. return 0;
  536. }
  537. }
  538. p = (uint8_t *)(&pDHCPMSG->op);
  539. p = p + 240; // 240 = sizeof(RIP_MSG) + MAGIC_COOKIE size in RIP_MSG.opt - sizeof(RIP_MSG.opt)
  540. e = p + (len - 240);
  541. while ( p < e ) {
  542. switch ( *p ) {
  543. case endOption :
  544. p = e; // for break while(p < e)
  545. break;
  546. case padOption :
  547. p++;
  548. break;
  549. case dhcpMessageType :
  550. p++;
  551. p++;
  552. type = *p++;
  553. break;
  554. case subnetMask :
  555. p++;
  556. p++;
  557. DHCP_allocated_sn[0] = *p++;
  558. DHCP_allocated_sn[1] = *p++;
  559. DHCP_allocated_sn[2] = *p++;
  560. DHCP_allocated_sn[3] = *p++;
  561. break;
  562. case routersOnSubnet :
  563. p++;
  564. opt_len = *p++;
  565. DHCP_allocated_gw[0] = *p++;
  566. DHCP_allocated_gw[1] = *p++;
  567. DHCP_allocated_gw[2] = *p++;
  568. DHCP_allocated_gw[3] = *p++;
  569. p = p + (opt_len - 4);
  570. break;
  571. case dns :
  572. p++;
  573. opt_len = *p++;
  574. DHCP_allocated_dns[0] = *p++;
  575. DHCP_allocated_dns[1] = *p++;
  576. DHCP_allocated_dns[2] = *p++;
  577. DHCP_allocated_dns[3] = *p++;
  578. p = p + (opt_len - 4);
  579. break;
  580. case dhcpIPaddrLeaseTime :
  581. p++;
  582. opt_len = *p++;
  583. dhcp_lease_time = *p++;
  584. dhcp_lease_time = (dhcp_lease_time << 8) + *p++;
  585. dhcp_lease_time = (dhcp_lease_time << 8) + *p++;
  586. dhcp_lease_time = (dhcp_lease_time << 8) + *p++;
  587. #ifdef _DHCP_DEBUG_
  588. dhcp_lease_time = 10;
  589. #endif
  590. break;
  591. case dhcpServerIdentifier :
  592. p++;
  593. opt_len = *p++;
  594. DHCP_SIP[0] = *p++;
  595. DHCP_SIP[1] = *p++;
  596. DHCP_SIP[2] = *p++;
  597. DHCP_SIP[3] = *p++;
  598. DHCP_REAL_SIP[0]=svr_addr[0];
  599. DHCP_REAL_SIP[1]=svr_addr[1];
  600. DHCP_REAL_SIP[2]=svr_addr[2];
  601. DHCP_REAL_SIP[3]=svr_addr[3];
  602. break;
  603. default :
  604. p++;
  605. opt_len = *p++;
  606. p += opt_len;
  607. break;
  608. } // switch
  609. } // while
  610. } // if
  611. return type;
  612. }
  613. uint8_t DHCP_run(void)
  614. {
  615. uint8_t type;
  616. uint8_t ret;
  617. if(dhcp_state == STATE_DHCP_STOP) return DHCP_STOPPED;
  618. if(getSn_SR(DHCP_SOCKET) != SOCK_UDP)
  619. socket(DHCP_SOCKET, Sn_MR_UDP, DHCP_CLIENT_PORT, 0x00);
  620. ret = DHCP_RUNNING;
  621. type = parseDHCPMSG();
  622. switch ( dhcp_state ) {
  623. case STATE_DHCP_INIT :
  624. DHCP_allocated_ip[0] = 0;
  625. DHCP_allocated_ip[1] = 0;
  626. DHCP_allocated_ip[2] = 0;
  627. DHCP_allocated_ip[3] = 0;
  628. send_DHCP_DISCOVER();
  629. dhcp_state = STATE_DHCP_DISCOVER;
  630. break;
  631. case STATE_DHCP_DISCOVER :
  632. if (type == DHCP_OFFER){
  633. #ifdef _DHCP_DEBUG_
  634. printf("> Receive DHCP_OFFER\r\n");
  635. #endif
  636. DHCP_allocated_ip[0] = pDHCPMSG->yiaddr[0];
  637. DHCP_allocated_ip[1] = pDHCPMSG->yiaddr[1];
  638. DHCP_allocated_ip[2] = pDHCPMSG->yiaddr[2];
  639. DHCP_allocated_ip[3] = pDHCPMSG->yiaddr[3];
  640. send_DHCP_REQUEST();
  641. dhcp_state = STATE_DHCP_REQUEST;
  642. } else {
  643. ret = check_DHCP_timeout();
  644. }
  645. break;
  646. case STATE_DHCP_REQUEST :
  647. if (type == DHCP_ACK) {
  648. #ifdef _DHCP_DEBUG_
  649. printf("> Receive DHCP_ACK\r\n");
  650. #endif
  651. if (check_DHCP_leasedIP()) {
  652. // Network info assignment from DHCP
  653. dhcp_ip_assign();
  654. reset_DHCP_timeout();
  655. dhcp_state = STATE_DHCP_LEASED;
  656. } else {
  657. // IP address conflict occurred
  658. reset_DHCP_timeout();
  659. dhcp_ip_conflict();
  660. dhcp_state = STATE_DHCP_INIT;
  661. }
  662. } else if (type == DHCP_NAK) {
  663. #ifdef _DHCP_DEBUG_
  664. printf("> Receive DHCP_NACK\r\n");
  665. #endif
  666. reset_DHCP_timeout();
  667. dhcp_state = STATE_DHCP_DISCOVER;
  668. } else {
  669. ret = check_DHCP_timeout();
  670. }
  671. break;
  672. case STATE_DHCP_LEASED :
  673. ret = DHCP_IP_LEASED;
  674. if ((dhcp_lease_time != INFINITE_LEASETIME) && ((dhcp_lease_time/2) < dhcp_tick_1s)) {
  675. #ifdef _DHCP_DEBUG_
  676. printf("> Maintains the IP address \r\n");
  677. #endif
  678. type = 0;
  679. OLD_allocated_ip[0] = DHCP_allocated_ip[0];
  680. OLD_allocated_ip[1] = DHCP_allocated_ip[1];
  681. OLD_allocated_ip[2] = DHCP_allocated_ip[2];
  682. OLD_allocated_ip[3] = DHCP_allocated_ip[3];
  683. DHCP_XID++;
  684. send_DHCP_REQUEST();
  685. reset_DHCP_timeout();
  686. dhcp_state = STATE_DHCP_REREQUEST;
  687. }
  688. break;
  689. case STATE_DHCP_REREQUEST :
  690. ret = DHCP_IP_LEASED;
  691. if (type == DHCP_ACK) {
  692. dhcp_retry_count = 0;
  693. if (OLD_allocated_ip[0] != DHCP_allocated_ip[0] ||
  694. OLD_allocated_ip[1] != DHCP_allocated_ip[1] ||
  695. OLD_allocated_ip[2] != DHCP_allocated_ip[2] ||
  696. OLD_allocated_ip[3] != DHCP_allocated_ip[3])
  697. {
  698. ret = DHCP_IP_CHANGED;
  699. dhcp_ip_update();
  700. #ifdef _DHCP_DEBUG_
  701. printf(">IP changed.\r\n");
  702. #endif
  703. }
  704. #ifdef _DHCP_DEBUG_
  705. else printf(">IP is continued.\r\n");
  706. #endif
  707. reset_DHCP_timeout();
  708. dhcp_state = STATE_DHCP_LEASED;
  709. } else if (type == DHCP_NAK) {
  710. #ifdef _DHCP_DEBUG_
  711. printf("> Receive DHCP_NACK, Failed to maintain ip\r\n");
  712. #endif
  713. reset_DHCP_timeout();
  714. dhcp_state = STATE_DHCP_DISCOVER;
  715. } else ret = check_DHCP_timeout();
  716. break;
  717. default :
  718. break;
  719. }
  720. return ret;
  721. }
  722. void DHCP_stop(void)
  723. {
  724. close(DHCP_SOCKET);
  725. dhcp_state = STATE_DHCP_STOP;
  726. }
  727. uint8_t check_DHCP_timeout(void)
  728. {
  729. uint8_t ret = DHCP_RUNNING;
  730. if (dhcp_retry_count < MAX_DHCP_RETRY) {
  731. if (dhcp_tick_next < dhcp_tick_1s) {
  732. switch ( dhcp_state ) {
  733. case STATE_DHCP_DISCOVER :
  734. // printf("<<timeout>> state : STATE_DHCP_DISCOVER\r\n");
  735. send_DHCP_DISCOVER();
  736. break;
  737. case STATE_DHCP_REQUEST :
  738. // printf("<<timeout>> state : STATE_DHCP_REQUEST\r\n");
  739. send_DHCP_REQUEST();
  740. break;
  741. case STATE_DHCP_REREQUEST :
  742. // printf("<<timeout>> state : STATE_DHCP_REREQUEST\r\n");
  743. send_DHCP_REQUEST();
  744. break;
  745. default :
  746. break;
  747. }
  748. dhcp_tick_1s = 0;
  749. dhcp_tick_next = dhcp_tick_1s + DHCP_WAIT_TIME;
  750. dhcp_retry_count++;
  751. }
  752. } else { // timeout occurred
  753. switch(dhcp_state) {
  754. case STATE_DHCP_DISCOVER:
  755. dhcp_state = STATE_DHCP_INIT;
  756. ret = DHCP_FAILED;
  757. break;
  758. case STATE_DHCP_REQUEST:
  759. case STATE_DHCP_REREQUEST:
  760. send_DHCP_DISCOVER();
  761. dhcp_state = STATE_DHCP_DISCOVER;
  762. break;
  763. default :
  764. break;
  765. }
  766. reset_DHCP_timeout();
  767. }
  768. return ret;
  769. }
  770. int8_t check_DHCP_leasedIP(void)
  771. {
  772. uint8_t tmp;
  773. int32_t ret;
  774. //WIZchip RCR value changed for ARP Timeout count control
  775. tmp = getRCR();
  776. setRCR(0x03);
  777. // IP conflict detection : ARP request - ARP reply
  778. // Broadcasting ARP Request for check the IP conflict using UDP sendto() function
  779. ret = sendto(DHCP_SOCKET, (uint8_t *)"CHECK_IP_CONFLICT", 17, DHCP_allocated_ip, 5000);
  780. // RCR value restore
  781. setRCR(tmp);
  782. if(ret == SOCKERR_TIMEOUT) {
  783. // UDP send Timeout occurred : allocated IP address is unique, DHCP Success
  784. #ifdef _DHCP_DEBUG_
  785. printf("\r\n> Check leased IP - OK\r\n");
  786. #endif
  787. return 1;
  788. } else {
  789. // Received ARP reply or etc : IP address conflict occur, DHCP Failed
  790. send_DHCP_DECLINE();
  791. ret = dhcp_tick_1s;
  792. while((dhcp_tick_1s - ret) < 2) ; // wait for 1s over; wait to complete to send DECLINE message;
  793. return 0;
  794. }
  795. }
  796. void DHCP_init(uint8_t s, uint8_t * buf)
  797. {
  798. uint8_t zeroip[4] = {0,0,0,0};
  799. getSHAR(DHCP_CHADDR);
  800. if((DHCP_CHADDR[0] | DHCP_CHADDR[1] | DHCP_CHADDR[2] | DHCP_CHADDR[3] | DHCP_CHADDR[4] | DHCP_CHADDR[5]) == 0x00)
  801. {
  802. // assigning temporary mac address, you should be set SHAR before call this function.
  803. DHCP_CHADDR[0] = 0x00;
  804. DHCP_CHADDR[1] = 0x08;
  805. DHCP_CHADDR[2] = 0xdc;
  806. DHCP_CHADDR[3] = 0x00;
  807. DHCP_CHADDR[4] = 0x00;
  808. DHCP_CHADDR[5] = 0x00;
  809. setSHAR(DHCP_CHADDR);
  810. }
  811. DHCP_SOCKET = s; // SOCK_DHCP
  812. pDHCPMSG = (RIP_MSG*)buf;
  813. DHCP_XID = 0x12345678;
  814. {
  815. DHCP_XID += DHCP_CHADDR[3];
  816. DHCP_XID += DHCP_CHADDR[4];
  817. DHCP_XID += DHCP_CHADDR[5];
  818. DHCP_XID += (DHCP_CHADDR[3] ^ DHCP_CHADDR[4] ^ DHCP_CHADDR[5]);
  819. }
  820. // WIZchip Netinfo Clear
  821. setSIPR(zeroip);
  822. setGAR(zeroip);
  823. reset_DHCP_timeout();
  824. dhcp_state = STATE_DHCP_INIT;
  825. }
  826. /* Reset the DHCP timeout count and retry count. */
  827. void reset_DHCP_timeout(void)
  828. {
  829. dhcp_tick_1s = 0;
  830. dhcp_tick_next = DHCP_WAIT_TIME;
  831. dhcp_retry_count = 0;
  832. }
  833. void DHCP_time_handler(void)
  834. {
  835. dhcp_tick_1s++;
  836. }
  837. void getIPfromDHCP(uint8_t* ip)
  838. {
  839. ip[0] = DHCP_allocated_ip[0];
  840. ip[1] = DHCP_allocated_ip[1];
  841. ip[2] = DHCP_allocated_ip[2];
  842. ip[3] = DHCP_allocated_ip[3];
  843. }
  844. void getGWfromDHCP(uint8_t* ip)
  845. {
  846. ip[0] =DHCP_allocated_gw[0];
  847. ip[1] =DHCP_allocated_gw[1];
  848. ip[2] =DHCP_allocated_gw[2];
  849. ip[3] =DHCP_allocated_gw[3];
  850. }
  851. void getSNfromDHCP(uint8_t* ip)
  852. {
  853. ip[0] = DHCP_allocated_sn[0];
  854. ip[1] = DHCP_allocated_sn[1];
  855. ip[2] = DHCP_allocated_sn[2];
  856. ip[3] = DHCP_allocated_sn[3];
  857. }
  858. void getDNSfromDHCP(uint8_t* ip)
  859. {
  860. ip[0] = DHCP_allocated_dns[0];
  861. ip[1] = DHCP_allocated_dns[1];
  862. ip[2] = DHCP_allocated_dns[2];
  863. ip[3] = DHCP_allocated_dns[3];
  864. }
  865. uint32_t getDHCPLeasetime(void)
  866. {
  867. return dhcp_lease_time;
  868. }
  869. char NibbleToHex(uint8_t nibble)
  870. {
  871. nibble &= 0x0F;
  872. if (nibble <= 9)
  873. return nibble + '0';
  874. else
  875. return nibble + ('A'-0x0A);
  876. }