dhcp.c 31 KB

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