dhcp.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978
  1. //*****************************************************************************
  2. //
  3. //! \file dhcp.c
  4. //! \brief DHCP APIs implement file.
  5. //! \details Processig DHCP protocol as DISCOVER, OFFER, REQUEST, ACK, NACK and DECLINE.
  6. //! \version 1.1.0
  7. //! \date 2013/11/18
  8. //! \par Revision history
  9. //! <2013/11/18> 1st Release
  10. //! <2012/12/20> V1.1.0
  11. //! 1. Optimize code
  12. //! 2. Add reg_dhcp_cbfunc()
  13. //! 3. Add DHCP_stop()
  14. //! 4. Integrate check_DHCP_state() & DHCP_run() to DHCP_run()
  15. //! 5. Don't care system endian
  16. //! 6. Add comments
  17. //! <2012/12/26> V1.1.1
  18. //! 1. Modify variable declaration: dhcp_tick_1s is declared volatile for code optimization
  19. //! \author Eric Jung & MidnightCow
  20. //! \copyright
  21. //!
  22. //! Copyright (c) 2013, WIZnet Co., LTD.
  23. //! All rights reserved.
  24. //!
  25. //! Redistribution and use in source and binary forms, with or without
  26. //! modification, are permitted provided that the following conditions
  27. //! are met:
  28. //!
  29. //! * Redistributions of source code must retain the above copyright
  30. //! notice, this list of conditions and the following disclaimer.
  31. //! * Redistributions in binary form must reproduce the above copyright
  32. //! notice, this list of conditions and the following disclaimer in the
  33. //! documentation and/or other materials provided with the distribution.
  34. //! * Neither the name of the <ORGANIZATION> nor the names of its
  35. //! contributors may be used to endorse or promote products derived
  36. //! from this software without specific prior written permission.
  37. //!
  38. //! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  39. //! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  40. //! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  41. //! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  42. //! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  43. //! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  44. //! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  45. //! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  46. //! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  47. //! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  48. //! THE POSSIBILITY OF SUCH DAMAGE.
  49. //
  50. //*****************************************************************************
  51. //#include "Ethernet/socket.h"
  52. //#include "Internet/DHCP/dhcp.h"
  53. #include "../../Ethernet/socket.h"
  54. #include "dhcp.h"
  55. /* If you want to display debug & processing message, Define _DHCP_DEBUG_ in dhcp.h */
  56. #ifdef _DHCP_DEBUG_
  57. #include <stdio.h>
  58. #endif
  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. {
  94. padOption = 0,
  95. subnetMask = 1,
  96. timerOffset = 2,
  97. routersOnSubnet = 3,
  98. timeServer = 4,
  99. nameServer = 5,
  100. dns = 6,
  101. logServer = 7,
  102. cookieServer = 8,
  103. lprServer = 9,
  104. impressServer = 10,
  105. resourceLocationServer = 11,
  106. hostName = 12,
  107. bootFileSize = 13,
  108. meritDumpFile = 14,
  109. domainName = 15,
  110. swapServer = 16,
  111. rootPath = 17,
  112. extentionsPath = 18,
  113. IPforwarding = 19,
  114. nonLocalSourceRouting = 20,
  115. policyFilter = 21,
  116. maxDgramReasmSize = 22,
  117. defaultIPTTL = 23,
  118. pathMTUagingTimeout = 24,
  119. pathMTUplateauTable = 25,
  120. ifMTU = 26,
  121. allSubnetsLocal = 27,
  122. broadcastAddr = 28,
  123. performMaskDiscovery = 29,
  124. maskSupplier = 30,
  125. performRouterDiscovery = 31,
  126. routerSolicitationAddr = 32,
  127. staticRoute = 33,
  128. trailerEncapsulation = 34,
  129. arpCacheTimeout = 35,
  130. ethernetEncapsulation = 36,
  131. tcpDefaultTTL = 37,
  132. tcpKeepaliveInterval = 38,
  133. tcpKeepaliveGarbage = 39,
  134. nisDomainName = 40,
  135. nisServers = 41,
  136. ntpServers = 42,
  137. vendorSpecificInfo = 43,
  138. netBIOSnameServer = 44,
  139. netBIOSdgramDistServer = 45,
  140. netBIOSnodeType = 46,
  141. netBIOSscope = 47,
  142. xFontServer = 48,
  143. xDisplayManager = 49,
  144. dhcpRequestedIPaddr = 50,
  145. dhcpIPaddrLeaseTime = 51,
  146. dhcpOptionOverload = 52,
  147. dhcpMessageType = 53,
  148. dhcpServerIdentifier = 54,
  149. dhcpParamRequest = 55,
  150. dhcpMsg = 56,
  151. dhcpMaxMsgSize = 57,
  152. dhcpT1value = 58,
  153. dhcpT2value = 59,
  154. dhcpClassIdentifier = 60,
  155. dhcpClientIdentifier = 61,
  156. endOption = 255
  157. };
  158. /*
  159. * @brief DHCP message format
  160. */
  161. typedef struct {
  162. uint8_t op; ///< @ref DHCP_BOOTREQUEST or @ref DHCP_BOOTREPLY
  163. uint8_t htype; ///< @ref DHCP_HTYPE10MB or @ref DHCP_HTYPE100MB
  164. uint8_t hlen; ///< @ref DHCP_HLENETHERNET
  165. uint8_t hops; ///< @ref DHCP_HOPS
  166. uint32_t xid; ///< @ref DHCP_XID This increase one every DHCP transaction.
  167. uint16_t secs; ///< @ref DHCP_SECS
  168. uint16_t flags; ///< @ref DHCP_FLAGSBROADCAST or @ref DHCP_FLAGSUNICAST
  169. uint8_t ciaddr[4]; ///< @ref Request IP to DHCP sever
  170. uint8_t yiaddr[4]; ///< @ref Offered IP from DHCP server
  171. uint8_t siaddr[4]; ///< No use
  172. uint8_t giaddr[4]; ///< No use
  173. uint8_t chaddr[16]; ///< DHCP client 6bytes MAC address. Others is filled to zero
  174. uint8_t sname[64]; ///< No use
  175. uint8_t file[128]; ///< No use
  176. uint8_t OPT[OPT_SIZE]; ///< Option
  177. } RIP_MSG;
  178. uint8_t DHCP_SOCKET; // Socket number for DHCP
  179. uint8_t DHCP_SIP[4]; // DHCP Server IP address
  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. /* send DISCOVER message to DHCP server */
  205. void send_DHCP_DISCOVER(void);
  206. /* send REQEUST message to DHCP server */
  207. void send_DHCP_REQUEST(void);
  208. /* send DECLINE message to DHCP server */
  209. void send_DHCP_DECLINE(void);
  210. /* IP conflict check by sending ARP-request to leased IP and wait ARP-response. */
  211. int8_t check_DHCP_leasedIP(void);
  212. /* check the timeout in DHCP process */
  213. uint8_t check_DHCP_timeout(void);
  214. /* Intialize to timeout process. */
  215. void reset_DHCP_timeout(void);
  216. /* Parse message as OFFER and ACK and NACK from DHCP server.*/
  217. int8_t parseDHCPCMSG(void);
  218. /* The default handler of ip assign first */
  219. void default_ip_assign(void)
  220. {
  221. setSIPR(DHCP_allocated_ip);
  222. setSUBR(DHCP_allocated_sn);
  223. setGAR (DHCP_allocated_gw);
  224. }
  225. /* The default handler of ip changed */
  226. void default_ip_update(void)
  227. {
  228. /* WIZchip Software Reset */
  229. setMR(MR_RST);
  230. getMR(); // for delay
  231. default_ip_assign();
  232. setSHAR(DHCP_CHADDR);
  233. }
  234. /* The default handler of ip changed */
  235. void default_ip_conflict(void)
  236. {
  237. // WIZchip Software Reset
  238. setMR(MR_RST);
  239. getMR(); // for delay
  240. setSHAR(DHCP_CHADDR);
  241. }
  242. /* register the call back func. */
  243. void reg_dhcp_cbfunc(void(*ip_assign)(void), void(*ip_update)(void), void(*ip_conflict)(void))
  244. {
  245. dhcp_ip_assign = default_ip_assign;
  246. dhcp_ip_update = default_ip_update;
  247. dhcp_ip_conflict = default_ip_conflict;
  248. if(ip_assign) dhcp_ip_assign = ip_assign;
  249. if(ip_update) dhcp_ip_update = ip_update;
  250. if(ip_conflict) dhcp_ip_conflict = ip_conflict;
  251. }
  252. /* make the common DHCP message */
  253. void makeDHCPMSG(void)
  254. {
  255. uint8_t bk_mac[6];
  256. uint8_t* ptmp;
  257. uint8_t i;
  258. getSHAR(bk_mac);
  259. pDHCPMSG->op = DHCP_BOOTREQUEST;
  260. pDHCPMSG->htype = DHCP_HTYPE10MB;
  261. pDHCPMSG->hlen = DHCP_HLENETHERNET;
  262. pDHCPMSG->hops = DHCP_HOPS;
  263. ptmp = (uint8_t*)(&pDHCPMSG->xid);
  264. *(ptmp+0) = (uint8_t)((DHCP_XID & 0xFF000000) >> 24);
  265. *(ptmp+1) = (uint8_t)((DHCP_XID & 0x00FF0000) >> 16);
  266. *(ptmp+2) = (uint8_t)((DHCP_XID & 0x0000FF00) >> 8);
  267. *(ptmp+3) = (uint8_t)((DHCP_XID & 0x000000FF) >> 0);
  268. pDHCPMSG->secs = DHCP_SECS;
  269. ptmp = (uint8_t*)(&pDHCPMSG->flags);
  270. *(ptmp+0) = (uint8_t)((DHCP_FLAGSBROADCAST & 0xFF00) >> 8);
  271. *(ptmp+1) = (uint8_t)((DHCP_FLAGSBROADCAST & 0x00FF) >> 0);
  272. pDHCPMSG->ciaddr[0] = 0;
  273. pDHCPMSG->ciaddr[1] = 0;
  274. pDHCPMSG->ciaddr[2] = 0;
  275. pDHCPMSG->ciaddr[3] = 0;
  276. pDHCPMSG->yiaddr[0] = 0;
  277. pDHCPMSG->yiaddr[1] = 0;
  278. pDHCPMSG->yiaddr[2] = 0;
  279. pDHCPMSG->yiaddr[3] = 0;
  280. pDHCPMSG->siaddr[0] = 0;
  281. pDHCPMSG->siaddr[1] = 0;
  282. pDHCPMSG->siaddr[2] = 0;
  283. pDHCPMSG->siaddr[3] = 0;
  284. pDHCPMSG->giaddr[0] = 0;
  285. pDHCPMSG->giaddr[1] = 0;
  286. pDHCPMSG->giaddr[2] = 0;
  287. pDHCPMSG->giaddr[3] = 0;
  288. pDHCPMSG->chaddr[0] = DHCP_CHADDR[0];
  289. pDHCPMSG->chaddr[1] = DHCP_CHADDR[1];
  290. pDHCPMSG->chaddr[2] = DHCP_CHADDR[2];
  291. pDHCPMSG->chaddr[3] = DHCP_CHADDR[3];
  292. pDHCPMSG->chaddr[4] = DHCP_CHADDR[4];
  293. pDHCPMSG->chaddr[5] = DHCP_CHADDR[5];
  294. for (i = 6; i < 16; i++) pDHCPMSG->chaddr[i] = 0;
  295. for (i = 0; i < 64; i++) pDHCPMSG->sname[i] = 0;
  296. for (i = 0; i < 128; i++) pDHCPMSG->file[i] = 0;
  297. // MAGIC_COOKIE
  298. pDHCPMSG->OPT[0] = (uint8_t)((MAGIC_COOKIE & 0xFF000000) >> 24);
  299. pDHCPMSG->OPT[1] = (uint8_t)((MAGIC_COOKIE & 0x00FF0000) >> 16);
  300. pDHCPMSG->OPT[2] = (uint8_t)((MAGIC_COOKIE & 0x0000FF00) >> 8);
  301. pDHCPMSG->OPT[3] = (uint8_t) (MAGIC_COOKIE & 0x000000FF) >> 0;
  302. }
  303. /* SEND DHCP DISCOVER */
  304. void send_DHCP_DISCOVER(void)
  305. {
  306. uint16_t i;
  307. uint8_t ip[4];
  308. uint16_t k = 0;
  309. makeDHCPMSG();
  310. k = 4; // because MAGIC_COOKIE already made by makeDHCPMSG()
  311. // Option Request Param
  312. pDHCPMSG->OPT[k++] = dhcpMessageType;
  313. pDHCPMSG->OPT[k++] = 0x01;
  314. pDHCPMSG->OPT[k++] = DHCP_DISCOVER;
  315. // Client identifier
  316. pDHCPMSG->OPT[k++] = dhcpClientIdentifier;
  317. pDHCPMSG->OPT[k++] = 0x07;
  318. pDHCPMSG->OPT[k++] = 0x01;
  319. pDHCPMSG->OPT[k++] = DHCP_CHADDR[0];
  320. pDHCPMSG->OPT[k++] = DHCP_CHADDR[1];
  321. pDHCPMSG->OPT[k++] = DHCP_CHADDR[2];
  322. pDHCPMSG->OPT[k++] = DHCP_CHADDR[3];
  323. pDHCPMSG->OPT[k++] = DHCP_CHADDR[4];
  324. pDHCPMSG->OPT[k++] = DHCP_CHADDR[5];
  325. // host name
  326. pDHCPMSG->OPT[k++] = hostName;
  327. pDHCPMSG->OPT[k++] = 0; // fill zero length of hostname
  328. for(i = 0 ; HOST_NAME[i] != 0; i++)
  329. pDHCPMSG->OPT[k++] = HOST_NAME[i];
  330. pDHCPMSG->OPT[k++] = DHCP_CHADDR[3];
  331. pDHCPMSG->OPT[k++] = DHCP_CHADDR[4];
  332. pDHCPMSG->OPT[k++] = DHCP_CHADDR[5];
  333. pDHCPMSG->OPT[k - (i+3+1)] = i+3; // length of hostname
  334. pDHCPMSG->OPT[k++] = dhcpParamRequest;
  335. pDHCPMSG->OPT[k++] = 0x06; // length of request
  336. pDHCPMSG->OPT[k++] = subnetMask;
  337. pDHCPMSG->OPT[k++] = routersOnSubnet;
  338. pDHCPMSG->OPT[k++] = dns;
  339. pDHCPMSG->OPT[k++] = domainName;
  340. pDHCPMSG->OPT[k++] = dhcpT1value;
  341. pDHCPMSG->OPT[k++] = dhcpT2value;
  342. pDHCPMSG->OPT[k++] = endOption;
  343. for (i = k; i < OPT_SIZE; i++) pDHCPMSG->OPT[i] = 0;
  344. // send broadcasting packet
  345. ip[0] = 255;
  346. ip[1] = 255;
  347. ip[2] = 255;
  348. ip[3] = 255;
  349. #ifdef _DHCP_DEBUG_
  350. printf("> Send DHCP_DISCOVER\r\n");
  351. #endif
  352. sendto(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT);
  353. }
  354. /* SEND DHCP REQUEST */
  355. void send_DHCP_REQUEST(void)
  356. {
  357. int i;
  358. uint8_t ip[4];
  359. uint16_t k = 0;
  360. makeDHCPMSG();
  361. if(dhcp_state == STATE_DHCP_LEASED || dhcp_state == STATE_DHCP_REREQUEST)
  362. {
  363. *((uint8_t*)(&pDHCPMSG->flags)) = ((DHCP_FLAGSUNICAST & 0xFF00)>> 8);
  364. *((uint8_t*)(&pDHCPMSG->flags)+1) = (DHCP_FLAGSUNICAST & 0x00FF);
  365. pDHCPMSG->ciaddr[0] = DHCP_allocated_ip[0];
  366. pDHCPMSG->ciaddr[1] = DHCP_allocated_ip[1];
  367. pDHCPMSG->ciaddr[2] = DHCP_allocated_ip[2];
  368. pDHCPMSG->ciaddr[3] = DHCP_allocated_ip[3];
  369. ip[0] = DHCP_SIP[0];
  370. ip[1] = DHCP_SIP[1];
  371. ip[2] = DHCP_SIP[2];
  372. ip[3] = DHCP_SIP[3];
  373. }
  374. else
  375. {
  376. ip[0] = 255;
  377. ip[1] = 255;
  378. ip[2] = 255;
  379. ip[3] = 255;
  380. }
  381. k = 4; // because MAGIC_COOKIE already made by makeDHCPMSG()
  382. // Option Request Param.
  383. pDHCPMSG->OPT[k++] = dhcpMessageType;
  384. pDHCPMSG->OPT[k++] = 0x01;
  385. pDHCPMSG->OPT[k++] = DHCP_REQUEST;
  386. pDHCPMSG->OPT[k++] = dhcpClientIdentifier;
  387. pDHCPMSG->OPT[k++] = 0x07;
  388. pDHCPMSG->OPT[k++] = 0x01;
  389. pDHCPMSG->OPT[k++] = DHCP_CHADDR[0];
  390. pDHCPMSG->OPT[k++] = DHCP_CHADDR[1];
  391. pDHCPMSG->OPT[k++] = DHCP_CHADDR[2];
  392. pDHCPMSG->OPT[k++] = DHCP_CHADDR[3];
  393. pDHCPMSG->OPT[k++] = DHCP_CHADDR[4];
  394. pDHCPMSG->OPT[k++] = DHCP_CHADDR[5];
  395. if(ip[3] == 255) // if(dchp_state == STATE_DHCP_LEASED || dchp_state == DHCP_REREQUEST_STATE)
  396. {
  397. pDHCPMSG->OPT[k++] = dhcpRequestedIPaddr;
  398. pDHCPMSG->OPT[k++] = 0x04;
  399. pDHCPMSG->OPT[k++] = DHCP_allocated_ip[0];
  400. pDHCPMSG->OPT[k++] = DHCP_allocated_ip[1];
  401. pDHCPMSG->OPT[k++] = DHCP_allocated_ip[2];
  402. pDHCPMSG->OPT[k++] = DHCP_allocated_ip[3];
  403. pDHCPMSG->OPT[k++] = dhcpServerIdentifier;
  404. pDHCPMSG->OPT[k++] = 0x04;
  405. pDHCPMSG->OPT[k++] = DHCP_SIP[0];
  406. pDHCPMSG->OPT[k++] = DHCP_SIP[1];
  407. pDHCPMSG->OPT[k++] = DHCP_SIP[2];
  408. pDHCPMSG->OPT[k++] = DHCP_SIP[3];
  409. }
  410. // host name
  411. pDHCPMSG->OPT[k++] = hostName;
  412. pDHCPMSG->OPT[k++] = 0; // length of hostname
  413. for(i = 0 ; HOST_NAME[i] != 0; i++)
  414. pDHCPMSG->OPT[k++] = HOST_NAME[i];
  415. pDHCPMSG->OPT[k++] = DHCP_CHADDR[3];
  416. pDHCPMSG->OPT[k++] = DHCP_CHADDR[4];
  417. pDHCPMSG->OPT[k++] = DHCP_CHADDR[5];
  418. pDHCPMSG->OPT[k - (i+3+1)] = i+3; // length of hostname
  419. pDHCPMSG->OPT[k++] = dhcpParamRequest;
  420. pDHCPMSG->OPT[k++] = 0x08;
  421. pDHCPMSG->OPT[k++] = subnetMask;
  422. pDHCPMSG->OPT[k++] = routersOnSubnet;
  423. pDHCPMSG->OPT[k++] = dns;
  424. pDHCPMSG->OPT[k++] = domainName;
  425. pDHCPMSG->OPT[k++] = dhcpT1value;
  426. pDHCPMSG->OPT[k++] = dhcpT2value;
  427. pDHCPMSG->OPT[k++] = performRouterDiscovery;
  428. pDHCPMSG->OPT[k++] = staticRoute;
  429. pDHCPMSG->OPT[k++] = endOption;
  430. for (i = k; i < OPT_SIZE; i++) pDHCPMSG->OPT[i] = 0;
  431. #ifdef _DHCP_DEBUG_
  432. printf("> Send DHCP_REQUEST\r\n");
  433. #endif
  434. sendto(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT);
  435. }
  436. /* SEND DHCP DHCPDECLINE */
  437. void send_DHCP_DECLINE(void)
  438. {
  439. int i;
  440. uint8_t ip[4];
  441. uint16_t k = 0;
  442. makeDHCPMSG();
  443. k = 4; // because MAGIC_COOKIE already made by makeDHCPMSG()
  444. *((uint8_t*)(&pDHCPMSG->flags)) = ((DHCP_FLAGSUNICAST & 0xFF00)>> 8);
  445. *((uint8_t*)(&pDHCPMSG->flags)+1) = (DHCP_FLAGSUNICAST & 0x00FF);
  446. // Option Request Param.
  447. pDHCPMSG->OPT[k++] = dhcpMessageType;
  448. pDHCPMSG->OPT[k++] = 0x01;
  449. pDHCPMSG->OPT[k++] = DHCP_DECLINE;
  450. pDHCPMSG->OPT[k++] = dhcpClientIdentifier;
  451. pDHCPMSG->OPT[k++] = 0x07;
  452. pDHCPMSG->OPT[k++] = 0x01;
  453. pDHCPMSG->OPT[k++] = DHCP_CHADDR[0];
  454. pDHCPMSG->OPT[k++] = DHCP_CHADDR[1];
  455. pDHCPMSG->OPT[k++] = DHCP_CHADDR[2];
  456. pDHCPMSG->OPT[k++] = DHCP_CHADDR[3];
  457. pDHCPMSG->OPT[k++] = DHCP_CHADDR[4];
  458. pDHCPMSG->OPT[k++] = DHCP_CHADDR[5];
  459. pDHCPMSG->OPT[k++] = dhcpRequestedIPaddr;
  460. pDHCPMSG->OPT[k++] = 0x04;
  461. pDHCPMSG->OPT[k++] = DHCP_allocated_ip[0];
  462. pDHCPMSG->OPT[k++] = DHCP_allocated_ip[1];
  463. pDHCPMSG->OPT[k++] = DHCP_allocated_ip[2];
  464. pDHCPMSG->OPT[k++] = DHCP_allocated_ip[3];
  465. pDHCPMSG->OPT[k++] = dhcpServerIdentifier;
  466. pDHCPMSG->OPT[k++] = 0x04;
  467. pDHCPMSG->OPT[k++] = DHCP_SIP[0];
  468. pDHCPMSG->OPT[k++] = DHCP_SIP[1];
  469. pDHCPMSG->OPT[k++] = DHCP_SIP[2];
  470. pDHCPMSG->OPT[k++] = DHCP_SIP[3];
  471. pDHCPMSG->OPT[k++] = endOption;
  472. for (i = k; i < OPT_SIZE; i++) pDHCPMSG->OPT[i] = 0;
  473. //send broadcasting packet
  474. ip[0] = 0xFF;
  475. ip[1] = 0xFF;
  476. ip[2] = 0xFF;
  477. ip[3] = 0xFF;
  478. #ifdef _DHCP_DEBUG_
  479. printf("\r\n> Send DHCP_DECLINE\r\n");
  480. #endif
  481. sendto(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT);
  482. }
  483. /* PARSE REPLY pDHCPMSG */
  484. int8_t parseDHCPMSG(void)
  485. {
  486. uint8_t svr_addr[6];
  487. uint16_t svr_port;
  488. uint16_t len;
  489. uint8_t * p;
  490. uint8_t * e;
  491. uint8_t type;
  492. uint8_t opt_len;
  493. if((len = getSn_RX_RSR(DHCP_SOCKET)) > 0)
  494. {
  495. len = recvfrom(DHCP_SOCKET, (uint8_t *)pDHCPMSG, len, svr_addr, &svr_port);
  496. #ifdef _DHCP_DEBUG_
  497. 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);
  498. #endif
  499. }
  500. else return 0;
  501. if (svr_port == DHCP_SERVER_PORT) {
  502. // compare mac address
  503. if ( (pDHCPMSG->chaddr[0] != DHCP_CHADDR[0]) || (pDHCPMSG->chaddr[1] != DHCP_CHADDR[1]) ||
  504. (pDHCPMSG->chaddr[2] != DHCP_CHADDR[2]) || (pDHCPMSG->chaddr[3] != DHCP_CHADDR[3]) ||
  505. (pDHCPMSG->chaddr[4] != DHCP_CHADDR[4]) || (pDHCPMSG->chaddr[5] != DHCP_CHADDR[5]) )
  506. return 0;
  507. type = 0;
  508. p = (uint8_t *)(&pDHCPMSG->op);
  509. p = p + 240; // 240 = sizeof(RIP_MSG) + MAGIC_COOKIE size in RIP_MSG.opt - sizeof(RIP_MSG.opt)
  510. e = p + (len - 240);
  511. while ( p < e ) {
  512. switch ( *p ) {
  513. case endOption :
  514. p = e; // for break while(p < e)
  515. break;
  516. case padOption :
  517. p++;
  518. break;
  519. case dhcpMessageType :
  520. p++;
  521. p++;
  522. type = *p++;
  523. break;
  524. case subnetMask :
  525. p++;
  526. p++;
  527. DHCP_allocated_sn[0] = *p++;
  528. DHCP_allocated_sn[1] = *p++;
  529. DHCP_allocated_sn[2] = *p++;
  530. DHCP_allocated_sn[3] = *p++;
  531. break;
  532. case routersOnSubnet :
  533. p++;
  534. opt_len = *p++;
  535. DHCP_allocated_gw[0] = *p++;
  536. DHCP_allocated_gw[1] = *p++;
  537. DHCP_allocated_gw[2] = *p++;
  538. DHCP_allocated_gw[3] = *p++;
  539. p = p + (opt_len - 4);
  540. break;
  541. case dns :
  542. p++;
  543. opt_len = *p++;
  544. DHCP_allocated_dns[0] = *p++;
  545. DHCP_allocated_dns[1] = *p++;
  546. DHCP_allocated_dns[2] = *p++;
  547. DHCP_allocated_dns[3] = *p++;
  548. p = p + (opt_len - 4);
  549. break;
  550. case dhcpIPaddrLeaseTime :
  551. p++;
  552. opt_len = *p++;
  553. dhcp_lease_time = *p++;
  554. dhcp_lease_time = (dhcp_lease_time << 8) + *p++;
  555. dhcp_lease_time = (dhcp_lease_time << 8) + *p++;
  556. dhcp_lease_time = (dhcp_lease_time << 8) + *p++;
  557. #ifdef _DHCP_DEBUG_
  558. dhcp_lease_time = 10;
  559. #endif
  560. break;
  561. case dhcpServerIdentifier :
  562. p++;
  563. opt_len = *p++;
  564. DHCP_SIP[0] = *p++;
  565. DHCP_SIP[1] = *p++;
  566. DHCP_SIP[2] = *p++;
  567. DHCP_SIP[3] = *p++;
  568. break;
  569. default :
  570. p++;
  571. opt_len = *p++;
  572. p += opt_len;
  573. break;
  574. } // switch
  575. } // while
  576. } // if
  577. return type;
  578. }
  579. uint8_t DHCP_run(void)
  580. {
  581. uint8_t type;
  582. uint8_t ret;
  583. if(dhcp_state == STATE_DHCP_STOP) return DHCP_STOPPED;
  584. if(getSn_SR(DHCP_SOCKET) != SOCK_UDP)
  585. socket(DHCP_SOCKET, Sn_MR_UDP, DHCP_CLIENT_PORT, 0x00);
  586. ret = DHCP_RUNNING;
  587. type = parseDHCPMSG();
  588. switch ( dhcp_state ) {
  589. case STATE_DHCP_INIT :
  590. DHCP_allocated_ip[0] = 0;
  591. DHCP_allocated_ip[1] = 0;
  592. DHCP_allocated_ip[2] = 0;
  593. DHCP_allocated_ip[3] = 0;
  594. send_DHCP_DISCOVER();
  595. dhcp_state = STATE_DHCP_DISCOVER;
  596. break;
  597. case STATE_DHCP_DISCOVER :
  598. if (type == DHCP_OFFER){
  599. #ifdef _DHCP_DEBUG_
  600. printf("> Receive DHCP_OFFER\r\n");
  601. #endif
  602. DHCP_allocated_ip[0] = pDHCPMSG->yiaddr[0];
  603. DHCP_allocated_ip[1] = pDHCPMSG->yiaddr[1];
  604. DHCP_allocated_ip[2] = pDHCPMSG->yiaddr[2];
  605. DHCP_allocated_ip[3] = pDHCPMSG->yiaddr[3];
  606. send_DHCP_REQUEST();
  607. dhcp_state = STATE_DHCP_REQUEST;
  608. } else ret = check_DHCP_timeout();
  609. break;
  610. case STATE_DHCP_REQUEST :
  611. if (type == DHCP_ACK) {
  612. #ifdef _DHCP_DEBUG_
  613. printf("> Receive DHCP_ACK\r\n");
  614. #endif
  615. if (check_DHCP_leasedIP()) {
  616. // Network info assignment from DHCP
  617. dhcp_ip_assign();
  618. reset_DHCP_timeout();
  619. dhcp_state = STATE_DHCP_LEASED;
  620. } else {
  621. // IP address conflict occurred
  622. reset_DHCP_timeout();
  623. dhcp_ip_conflict();
  624. dhcp_state = STATE_DHCP_INIT;
  625. }
  626. } else if (type == DHCP_NAK) {
  627. #ifdef _DHCP_DEBUG_
  628. printf("> Receive DHCP_NACK\r\n");
  629. #endif
  630. reset_DHCP_timeout();
  631. dhcp_state = STATE_DHCP_DISCOVER;
  632. } else ret = check_DHCP_timeout();
  633. break;
  634. case STATE_DHCP_LEASED :
  635. ret = DHCP_IP_LEASED;
  636. if ((dhcp_lease_time != INFINITE_LEASETIME) && ((dhcp_lease_time/2) < dhcp_tick_1s)) {
  637. #ifdef _DHCP_DEBUG_
  638. printf("> Maintains the IP address \r\n");
  639. #endif
  640. type = 0;
  641. OLD_allocated_ip[0] = DHCP_allocated_ip[0];
  642. OLD_allocated_ip[1] = DHCP_allocated_ip[1];
  643. OLD_allocated_ip[2] = DHCP_allocated_ip[2];
  644. OLD_allocated_ip[3] = DHCP_allocated_ip[3];
  645. DHCP_XID++;
  646. send_DHCP_REQUEST();
  647. reset_DHCP_timeout();
  648. dhcp_state = STATE_DHCP_REREQUEST;
  649. }
  650. break;
  651. case STATE_DHCP_REREQUEST :
  652. ret = DHCP_IP_LEASED;
  653. if (type == DHCP_ACK) {
  654. dhcp_retry_count = 0;
  655. if (OLD_allocated_ip[0] != DHCP_allocated_ip[0] ||
  656. OLD_allocated_ip[1] != DHCP_allocated_ip[1] ||
  657. OLD_allocated_ip[2] != DHCP_allocated_ip[2] ||
  658. OLD_allocated_ip[3] != DHCP_allocated_ip[3])
  659. {
  660. ret = DHCP_IP_CHANGED;
  661. dhcp_ip_update();
  662. #ifdef _DHCP_DEBUG_
  663. printf(">IP changed.\r\n");
  664. #endif
  665. }
  666. #ifdef _DHCP_DEBUG_
  667. else printf(">IP is continued.\r\n");
  668. #endif
  669. reset_DHCP_timeout();
  670. dhcp_state = STATE_DHCP_LEASED;
  671. } else if (type == DHCP_NAK) {
  672. #ifdef _DHCP_DEBUG_
  673. printf("> Receive DHCP_NACK, Failed to maintain ip\r\n");
  674. #endif
  675. reset_DHCP_timeout();
  676. dhcp_state = STATE_DHCP_DISCOVER;
  677. } else ret = check_DHCP_timeout();
  678. break;
  679. default :
  680. break;
  681. }
  682. return ret;
  683. }
  684. void DHCP_stop(void)
  685. {
  686. close(DHCP_SOCKET);
  687. dhcp_state = STATE_DHCP_STOP;
  688. }
  689. uint8_t check_DHCP_timeout(void)
  690. {
  691. uint8_t ret = DHCP_RUNNING;
  692. if (dhcp_retry_count < MAX_DHCP_RETRY) {
  693. if (dhcp_tick_next < dhcp_tick_1s) {
  694. switch ( dhcp_state ) {
  695. case STATE_DHCP_DISCOVER :
  696. // printf("<<timeout>> state : STATE_DHCP_DISCOVER\r\n");
  697. send_DHCP_DISCOVER();
  698. break;
  699. case STATE_DHCP_REQUEST :
  700. // printf("<<timeout>> state : STATE_DHCP_REQUEST\r\n");
  701. send_DHCP_REQUEST();
  702. break;
  703. case STATE_DHCP_REREQUEST :
  704. // printf("<<timeout>> state : STATE_DHCP_REREQUEST\r\n");
  705. send_DHCP_REQUEST();
  706. break;
  707. default :
  708. break;
  709. }
  710. dhcp_tick_1s = 0;
  711. dhcp_tick_next = dhcp_tick_1s + DHCP_WAIT_TIME;
  712. dhcp_retry_count++;
  713. }
  714. } else { // timeout occurred
  715. switch(dhcp_state) {
  716. case STATE_DHCP_DISCOVER:
  717. dhcp_state = STATE_DHCP_INIT;
  718. ret = DHCP_FAILED;
  719. break;
  720. case STATE_DHCP_REQUEST:
  721. case STATE_DHCP_REREQUEST:
  722. send_DHCP_DISCOVER();
  723. dhcp_state = STATE_DHCP_DISCOVER;
  724. break;
  725. default :
  726. break;
  727. }
  728. reset_DHCP_timeout();
  729. }
  730. return ret;
  731. }
  732. int8_t check_DHCP_leasedIP(void)
  733. {
  734. uint8_t tmp;
  735. int32_t ret;
  736. //WIZchip RCR value changed for ARP Timeout count control
  737. tmp = getRCR();
  738. setRCR(0x03);
  739. // IP conflict detection : ARP request - ARP reply
  740. // Broadcasting ARP Request for check the IP conflict using UDP sendto() function
  741. ret = sendto(DHCP_SOCKET, (uint8_t *)"CHECK_IP_CONFLICT", 17, DHCP_allocated_ip, 5000);
  742. // RCR value restore
  743. setRCR(tmp);
  744. if(ret == SOCKERR_TIMEOUT) {
  745. // UDP send Timeout occurred : allocated IP address is unique, DHCP Success
  746. #ifdef _DHCP_DEBUG_
  747. printf("\r\n> Check leased IP - OK\r\n");
  748. #endif
  749. return 1;
  750. } else {
  751. // Received ARP reply or etc : IP address conflict occur, DHCP Failed
  752. send_DHCP_DECLINE();
  753. ret = dhcp_tick_1s;
  754. while((dhcp_tick_1s - ret) < 2) ; // wait for 1s over; wait to complete to send DECLINE message;
  755. return 0;
  756. }
  757. }
  758. void DHCP_init(uint8_t s, uint8_t * buf)
  759. {
  760. uint8_t zeroip[4] = {0,0,0,0};
  761. getSHAR(DHCP_CHADDR);
  762. if((DHCP_CHADDR[0] | DHCP_CHADDR[1] | DHCP_CHADDR[2] | DHCP_CHADDR[3] | DHCP_CHADDR[4] | DHCP_CHADDR[5]) == 0x00)
  763. {
  764. // assign temporary mac address, you should be set SHAR before call this function.
  765. DHCP_CHADDR[0] = 0x00;
  766. DHCP_CHADDR[1] = 0x08;
  767. DHCP_CHADDR[2] = 0xdc;
  768. DHCP_CHADDR[3] = 0x00;
  769. DHCP_CHADDR[4] = 0x00;
  770. DHCP_CHADDR[5] = 0x00;
  771. setSHAR(DHCP_CHADDR);
  772. }
  773. DHCP_SOCKET = s; // SOCK_DHCP
  774. pDHCPMSG = (RIP_MSG*)buf;
  775. DHCP_XID = 0x12345678;
  776. // WIZchip Netinfo Clear
  777. setSIPR(zeroip);
  778. setSIPR(zeroip);
  779. setGAR(zeroip);
  780. reset_DHCP_timeout();
  781. dhcp_state = STATE_DHCP_INIT;
  782. }
  783. /* Rset the DHCP timeout count and retry count. */
  784. void reset_DHCP_timeout(void)
  785. {
  786. dhcp_tick_1s = 0;
  787. dhcp_tick_next = DHCP_WAIT_TIME;
  788. dhcp_retry_count = 0;
  789. }
  790. void DHCP_time_handler(void)
  791. {
  792. dhcp_tick_1s++;
  793. }
  794. void getIPfromDHCP(uint8_t* ip)
  795. {
  796. ip[0] = DHCP_allocated_ip[0];
  797. ip[1] = DHCP_allocated_ip[1];
  798. ip[2] = DHCP_allocated_ip[2];
  799. ip[3] = DHCP_allocated_ip[3];
  800. }
  801. void getGWfromDHCP(uint8_t* ip)
  802. {
  803. ip[0] =DHCP_allocated_gw[0];
  804. ip[1] =DHCP_allocated_gw[1];
  805. ip[2] =DHCP_allocated_gw[2];
  806. ip[3] =DHCP_allocated_gw[3];
  807. }
  808. void getSNfromDHCP(uint8_t* ip)
  809. {
  810. ip[0] = DHCP_allocated_sn[0];
  811. ip[1] = DHCP_allocated_sn[1];
  812. ip[2] = DHCP_allocated_sn[2];
  813. ip[3] = DHCP_allocated_sn[3];
  814. }
  815. void getDNSfromDHCP(uint8_t* ip)
  816. {
  817. ip[0] = DHCP_allocated_dns[0];
  818. ip[1] = DHCP_allocated_dns[1];
  819. ip[2] = DHCP_allocated_dns[2];
  820. ip[3] = DHCP_allocated_dns[3];
  821. }
  822. uint32_t getDHCPLeasetime(void)
  823. {
  824. return dhcp_lease_time;
  825. }