dhcp.c 61 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722
  1. /**
  2. * @file
  3. * Dynamic Host Configuration Protocol client
  4. *
  5. */
  6. /*
  7. *
  8. * Copyright (c) 2001-2004 Leon Woestenberg <leon.woestenberg@gmx.net>
  9. * Copyright (c) 2001-2004 Axon Digital Design B.V., The Netherlands.
  10. * All rights reserved.
  11. *
  12. * Redistribution and use in source and binary forms, with or without modification,
  13. * are permitted provided that the following conditions are met:
  14. *
  15. * 1. Redistributions of source code must retain the above copyright notice,
  16. * this list of conditions and the following disclaimer.
  17. * 2. Redistributions in binary form must reproduce the above copyright notice,
  18. * this list of conditions and the following disclaimer in the documentation
  19. * and/or other materials provided with the distribution.
  20. * 3. The name of the author may not be used to endorse or promote products
  21. * derived from this software without specific prior written permission.
  22. *
  23. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
  24. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  25. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
  26. * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  27. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
  28. * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  29. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  30. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  31. * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  32. * OF SUCH DAMAGE.
  33. *
  34. * This file is a contribution to the lwIP TCP/IP stack.
  35. * The Swedish Institute of Computer Science and Adam Dunkels
  36. * are specifically granted permission to redistribute this
  37. * source code.
  38. *
  39. * Author: Leon Woestenberg <leon.woestenberg@gmx.net>
  40. *
  41. * This is a DHCP client for the lwIP TCP/IP stack. It aims to conform
  42. * with RFC 2131 and RFC 2132.
  43. *
  44. * TODO:
  45. * - Proper parsing of DHCP messages exploiting file/sname field overloading.
  46. * - Add JavaDoc style documentation (API, internals).
  47. * - Support for interfaces other than Ethernet (SLIP, PPP, ...)
  48. *
  49. * Please coordinate changes and requests with Leon Woestenberg
  50. * <leon.woestenberg@gmx.net>
  51. *
  52. * Integration with your code:
  53. *
  54. * In lwip/dhcp.h
  55. * #define DHCP_COARSE_TIMER_SECS (recommended 60 which is a minute)
  56. * #define DHCP_FINE_TIMER_MSECS (recommended 500 which equals TCP coarse timer)
  57. *
  58. * Then have your application call dhcp_coarse_tmr() and
  59. * dhcp_fine_tmr() on the defined intervals.
  60. *
  61. * dhcp_start(struct netif *netif);
  62. * starts a DHCP client instance which configures the interface by
  63. * obtaining an IP address lease and maintaining it.
  64. *
  65. * Use dhcp_release(netif) to end the lease and use dhcp_stop(netif)
  66. * to remove the DHCP client.
  67. *
  68. */
  69. #include "lwip/opt.h"
  70. #if LWIP_DHCP /* don't build if not configured for use in lwipopts.h */
  71. #include "lwip/stats.h"
  72. #include "lwip/mem.h"
  73. #include "lwip/udp.h"
  74. #include "lwip/ip_addr.h"
  75. #include "lwip/netif.h"
  76. #include "lwip/inet.h"
  77. #include "lwip/sys.h"
  78. #include "lwip/dhcp.h"
  79. #include "lwip/autoip.h"
  80. #include "lwip/dns.h"
  81. #include "netif/etharp.h"
  82. #include <string.h>
  83. /** Default for DHCP_GLOBAL_XID is 0xABCD0000
  84. * This can be changed by defining DHCP_GLOBAL_XID and DHCP_GLOBAL_XID_HEADER, e.g.
  85. * #define DHCP_GLOBAL_XID_HEADER "stdlib.h"
  86. * #define DHCP_GLOBAL_XID rand()
  87. */
  88. #ifdef DHCP_GLOBAL_XID_HEADER
  89. #include DHCP_GLOBAL_XID_HEADER /* include optional starting XID generation prototypes */
  90. #endif
  91. /** DHCP_OPTION_MAX_MSG_SIZE is set to the MTU
  92. * MTU is checked to be big enough in dhcp_start */
  93. #define DHCP_MAX_MSG_LEN(netif) (netif->mtu)
  94. #define DHCP_MAX_MSG_LEN_MIN_REQUIRED 576
  95. /** Minimum length for reply before packet is parsed */
  96. #define DHCP_MIN_REPLY_LEN 44
  97. #define REBOOT_TRIES 2
  98. /* DHCP client state machine functions */
  99. static void dhcp_handle_ack(struct netif *netif);
  100. static void dhcp_handle_nak(struct netif *netif);
  101. static void dhcp_handle_offer(struct netif *netif);
  102. static err_t dhcp_discover(struct netif *netif);
  103. static err_t dhcp_select(struct netif *netif);
  104. static void dhcp_bind(struct netif *netif);
  105. #if DHCP_DOES_ARP_CHECK
  106. static void dhcp_check(struct netif *netif);
  107. static err_t dhcp_decline(struct netif *netif);
  108. #endif /* DHCP_DOES_ARP_CHECK */
  109. static err_t dhcp_rebind(struct netif *netif);
  110. static err_t dhcp_reboot(struct netif *netif);
  111. static void dhcp_set_state(struct dhcp *dhcp, u8_t new_state);
  112. /* receive, unfold, parse and free incoming messages */
  113. static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port);
  114. static err_t dhcp_unfold_reply(struct dhcp *dhcp, struct pbuf *p);
  115. static u8_t *dhcp_get_option_ptr(struct dhcp *dhcp, u8_t option_type);
  116. static u8_t dhcp_get_option_byte(u8_t *ptr);
  117. #if 0
  118. static u16_t dhcp_get_option_short(u8_t *ptr);
  119. #endif
  120. static u32_t dhcp_get_option_long(u8_t *ptr);
  121. static void dhcp_free_reply(struct dhcp *dhcp);
  122. /* set the DHCP timers */
  123. static void dhcp_timeout(struct netif *netif);
  124. static void dhcp_t1_timeout(struct netif *netif);
  125. static void dhcp_t2_timeout(struct netif *netif);
  126. /* build outgoing messages */
  127. /* create a DHCP request, fill in common headers */
  128. static err_t dhcp_create_request(struct netif *netif);
  129. /* free a DHCP request */
  130. static void dhcp_delete_request(struct netif *netif);
  131. /* add a DHCP option (type, then length in bytes) */
  132. static void dhcp_option(struct dhcp *dhcp, u8_t option_type, u8_t option_len);
  133. /* add option values */
  134. static void dhcp_option_byte(struct dhcp *dhcp, u8_t value);
  135. static void dhcp_option_short(struct dhcp *dhcp, u16_t value);
  136. static void dhcp_option_long(struct dhcp *dhcp, u32_t value);
  137. /* always add the DHCP options trailer to end and pad */
  138. static void dhcp_option_trailer(struct dhcp *dhcp);
  139. /**
  140. * Back-off the DHCP client (because of a received NAK response).
  141. *
  142. * Back-off the DHCP client because of a received NAK. Receiving a
  143. * NAK means the client asked for something non-sensible, for
  144. * example when it tries to renew a lease obtained on another network.
  145. *
  146. * We clear any existing set IP address and restart DHCP negotiation
  147. * afresh (as per RFC2131 3.2.3).
  148. *
  149. * @param netif the netif under DHCP control
  150. */
  151. static void
  152. dhcp_handle_nak(struct netif *netif)
  153. {
  154. struct dhcp *dhcp = netif->dhcp;
  155. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_handle_nak(netif=%p) %c%c%"U16_F"\n",
  156. (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
  157. /* Set the interface down since the address must no longer be used, as per RFC2131 */
  158. netif_set_down(netif);
  159. /* remove IP address from interface */
  160. netif_set_ipaddr(netif, IP_ADDR_ANY);
  161. netif_set_gw(netif, IP_ADDR_ANY);
  162. netif_set_netmask(netif, IP_ADDR_ANY);
  163. /* Change to a defined state */
  164. dhcp_set_state(dhcp, DHCP_BACKING_OFF);
  165. /* We can immediately restart discovery */
  166. dhcp_discover(netif);
  167. }
  168. #if DHCP_DOES_ARP_CHECK
  169. /**
  170. * Checks if the offered IP address is already in use.
  171. *
  172. * It does so by sending an ARP request for the offered address and
  173. * entering CHECKING state. If no ARP reply is received within a small
  174. * interval, the address is assumed to be free for use by us.
  175. *
  176. * @param netif the netif under DHCP control
  177. */
  178. static void
  179. dhcp_check(struct netif *netif)
  180. {
  181. struct dhcp *dhcp = netif->dhcp;
  182. err_t result;
  183. u16_t msecs;
  184. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_check(netif=%p) %c%c\n", (void *)netif, (s16_t)netif->name[0],
  185. (s16_t)netif->name[1]));
  186. dhcp_set_state(dhcp, DHCP_CHECKING);
  187. /* create an ARP query for the offered IP address, expecting that no host
  188. responds, as the IP address should not be in use. */
  189. result = etharp_query(netif, &dhcp->offered_ip_addr, NULL);
  190. if (result != ERR_OK) {
  191. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("dhcp_check: could not perform ARP query\n"));
  192. }
  193. dhcp->tries++;
  194. msecs = 500;
  195. dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
  196. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_check(): set request timeout %"U16_F" msecs\n", msecs));
  197. }
  198. #endif /* DHCP_DOES_ARP_CHECK */
  199. /**
  200. * Remember the configuration offered by a DHCP server.
  201. *
  202. * @param netif the netif under DHCP control
  203. */
  204. static void
  205. dhcp_handle_offer(struct netif *netif)
  206. {
  207. struct dhcp *dhcp = netif->dhcp;
  208. /* obtain the server address */
  209. u8_t *option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_SERVER_ID);
  210. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_handle_offer(netif=%p) %c%c%"U16_F"\n",
  211. (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
  212. if (option_ptr != NULL) {
  213. dhcp->server_ip_addr.addr = htonl(dhcp_get_option_long(&option_ptr[2]));
  214. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_handle_offer(): server 0x%08"X32_F"\n", dhcp->server_ip_addr.addr));
  215. /* remember offered address */
  216. ip_addr_set(&dhcp->offered_ip_addr, (struct ip_addr *)&dhcp->msg_in->yiaddr);
  217. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_handle_offer(): offer for 0x%08"X32_F"\n", dhcp->offered_ip_addr.addr));
  218. dhcp_select(netif);
  219. }
  220. }
  221. /**
  222. * Select a DHCP server offer out of all offers.
  223. *
  224. * Simply select the first offer received.
  225. *
  226. * @param netif the netif under DHCP control
  227. * @return lwIP specific error (see error.h)
  228. */
  229. static err_t
  230. dhcp_select(struct netif *netif)
  231. {
  232. struct dhcp *dhcp = netif->dhcp;
  233. err_t result;
  234. u16_t msecs;
  235. #if LWIP_NETIF_HOSTNAME
  236. const char *p;
  237. #endif /* LWIP_NETIF_HOSTNAME */
  238. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_select(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
  239. dhcp_set_state(dhcp, DHCP_REQUESTING);
  240. /* create and initialize the DHCP message header */
  241. result = dhcp_create_request(netif);
  242. if (result == ERR_OK) {
  243. dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
  244. dhcp_option_byte(dhcp, DHCP_REQUEST);
  245. dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
  246. dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif));
  247. /* MUST request the offered IP address */
  248. dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
  249. dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr));
  250. dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4);
  251. dhcp_option_long(dhcp, ntohl(dhcp->server_ip_addr.addr));
  252. dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 4/*num options*/);
  253. dhcp_option_byte(dhcp, DHCP_OPTION_SUBNET_MASK);
  254. dhcp_option_byte(dhcp, DHCP_OPTION_ROUTER);
  255. dhcp_option_byte(dhcp, DHCP_OPTION_BROADCAST);
  256. dhcp_option_byte(dhcp, DHCP_OPTION_DNS_SERVER);
  257. #if LWIP_NETIF_HOSTNAME
  258. p = (const char*)netif->hostname;
  259. if (p != NULL) {
  260. dhcp_option(dhcp, DHCP_OPTION_HOSTNAME, strlen(p));
  261. while (*p) {
  262. dhcp_option_byte(dhcp, *p++);
  263. }
  264. }
  265. #endif /* LWIP_NETIF_HOSTNAME */
  266. dhcp_option_trailer(dhcp);
  267. /* shrink the pbuf to the actual content length */
  268. pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
  269. /* send broadcast to any DHCP server */
  270. udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
  271. dhcp_delete_request(netif);
  272. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_select: REQUESTING\n"));
  273. } else {
  274. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("dhcp_select: could not allocate DHCP request\n"));
  275. }
  276. dhcp->tries++;
  277. msecs = (dhcp->tries < 6 ? 1 << dhcp->tries : 60) * 1000;
  278. dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
  279. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_select(): set request timeout %"U16_F" msecs\n", msecs));
  280. return result;
  281. }
  282. /**
  283. * The DHCP timer that checks for lease renewal/rebind timeouts.
  284. *
  285. */
  286. void
  287. dhcp_coarse_tmr()
  288. {
  289. struct netif *netif = netif_list;
  290. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_coarse_tmr()\n"));
  291. /* iterate through all network interfaces */
  292. while (netif != NULL) {
  293. /* only act on DHCP configured interfaces */
  294. if (netif->dhcp != NULL) {
  295. /* timer is active (non zero), and triggers (zeroes) now? */
  296. if (netif->dhcp->t2_timeout-- == 1) {
  297. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_coarse_tmr(): t2 timeout\n"));
  298. /* this clients' rebind timeout triggered */
  299. dhcp_t2_timeout(netif);
  300. /* timer is active (non zero), and triggers (zeroes) now */
  301. } else if (netif->dhcp->t1_timeout-- == 1) {
  302. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_coarse_tmr(): t1 timeout\n"));
  303. /* this clients' renewal timeout triggered */
  304. dhcp_t1_timeout(netif);
  305. }
  306. }
  307. /* proceed to next netif */
  308. netif = netif->next;
  309. }
  310. }
  311. /**
  312. * DHCP transaction timeout handling
  313. *
  314. * A DHCP server is expected to respond within a short period of time.
  315. * This timer checks whether an outstanding DHCP request is timed out.
  316. *
  317. */
  318. void
  319. dhcp_fine_tmr()
  320. {
  321. struct netif *netif = netif_list;
  322. /* loop through netif's */
  323. while (netif != NULL) {
  324. /* only act on DHCP configured interfaces */
  325. if (netif->dhcp != NULL) {
  326. /* timer is active (non zero), and is about to trigger now */
  327. if (netif->dhcp->request_timeout > 1) {
  328. netif->dhcp->request_timeout--;
  329. }
  330. else if (netif->dhcp->request_timeout == 1) {
  331. netif->dhcp->request_timeout--;
  332. /* { netif->dhcp->request_timeout == 0 } */
  333. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_fine_tmr(): request timeout\n"));
  334. /* this clients' request timeout triggered */
  335. dhcp_timeout(netif);
  336. }
  337. }
  338. /* proceed to next network interface */
  339. netif = netif->next;
  340. }
  341. }
  342. /**
  343. * A DHCP negotiation transaction, or ARP request, has timed out.
  344. *
  345. * The timer that was started with the DHCP or ARP request has
  346. * timed out, indicating no response was received in time.
  347. *
  348. * @param netif the netif under DHCP control
  349. */
  350. static void
  351. dhcp_timeout(struct netif *netif)
  352. {
  353. struct dhcp *dhcp = netif->dhcp;
  354. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_timeout()\n"));
  355. /* back-off period has passed, or server selection timed out */
  356. if ((dhcp->state == DHCP_BACKING_OFF) || (dhcp->state == DHCP_SELECTING)) {
  357. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_timeout(): restarting discovery\n"));
  358. dhcp_discover(netif);
  359. /* receiving the requested lease timed out */
  360. } else if (dhcp->state == DHCP_REQUESTING) {
  361. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): REQUESTING, DHCP request timed out\n"));
  362. if (dhcp->tries <= 5) {
  363. dhcp_select(netif);
  364. } else {
  365. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): REQUESTING, releasing, restarting\n"));
  366. dhcp_release(netif);
  367. dhcp_discover(netif);
  368. }
  369. #if DHCP_DOES_ARP_CHECK
  370. /* received no ARP reply for the offered address (which is good) */
  371. } else if (dhcp->state == DHCP_CHECKING) {
  372. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): CHECKING, ARP request timed out\n"));
  373. if (dhcp->tries <= 1) {
  374. dhcp_check(netif);
  375. /* no ARP replies on the offered address,
  376. looks like the IP address is indeed free */
  377. } else {
  378. /* bind the interface to the offered address */
  379. dhcp_bind(netif);
  380. }
  381. #endif /* DHCP_DOES_ARP_CHECK */
  382. }
  383. /* did not get response to renew request? */
  384. else if (dhcp->state == DHCP_RENEWING) {
  385. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): RENEWING, DHCP request timed out\n"));
  386. /* just retry renewal */
  387. /* note that the rebind timer will eventually time-out if renew does not work */
  388. dhcp_renew(netif);
  389. /* did not get response to rebind request? */
  390. } else if (dhcp->state == DHCP_REBINDING) {
  391. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): REBINDING, DHCP request timed out\n"));
  392. if (dhcp->tries <= 8) {
  393. dhcp_rebind(netif);
  394. } else {
  395. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): RELEASING, DISCOVERING\n"));
  396. dhcp_release(netif);
  397. dhcp_discover(netif);
  398. }
  399. } else if (dhcp->state == DHCP_REBOOTING) {
  400. if (dhcp->tries < REBOOT_TRIES) {
  401. dhcp_reboot(netif);
  402. } else {
  403. dhcp_discover(netif);
  404. }
  405. }
  406. }
  407. /**
  408. * The renewal period has timed out.
  409. *
  410. * @param netif the netif under DHCP control
  411. */
  412. static void
  413. dhcp_t1_timeout(struct netif *netif)
  414. {
  415. struct dhcp *dhcp = netif->dhcp;
  416. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_t1_timeout()\n"));
  417. if ((dhcp->state == DHCP_REQUESTING) || (dhcp->state == DHCP_BOUND) || (dhcp->state == DHCP_RENEWING)) {
  418. /* just retry to renew - note that the rebind timer (t2) will
  419. * eventually time-out if renew tries fail. */
  420. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_t1_timeout(): must renew\n"));
  421. dhcp_renew(netif);
  422. }
  423. }
  424. /**
  425. * The rebind period has timed out.
  426. *
  427. * @param netif the netif under DHCP control
  428. */
  429. static void
  430. dhcp_t2_timeout(struct netif *netif)
  431. {
  432. struct dhcp *dhcp = netif->dhcp;
  433. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_t2_timeout()\n"));
  434. if ((dhcp->state == DHCP_REQUESTING) || (dhcp->state == DHCP_BOUND) || (dhcp->state == DHCP_RENEWING)) {
  435. /* just retry to rebind */
  436. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_t2_timeout(): must rebind\n"));
  437. dhcp_rebind(netif);
  438. }
  439. }
  440. /**
  441. * Handle a DHCP ACK packet
  442. *
  443. * @param netif the netif under DHCP control
  444. */
  445. static void
  446. dhcp_handle_ack(struct netif *netif)
  447. {
  448. struct dhcp *dhcp = netif->dhcp;
  449. u8_t *option_ptr;
  450. /* clear options we might not get from the ACK */
  451. dhcp->offered_sn_mask.addr = 0;
  452. dhcp->offered_gw_addr.addr = 0;
  453. dhcp->offered_bc_addr.addr = 0;
  454. /* lease time given? */
  455. option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_LEASE_TIME);
  456. if (option_ptr != NULL) {
  457. /* remember offered lease time */
  458. dhcp->offered_t0_lease = dhcp_get_option_long(option_ptr + 2);
  459. }
  460. /* renewal period given? */
  461. option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_T1);
  462. if (option_ptr != NULL) {
  463. /* remember given renewal period */
  464. dhcp->offered_t1_renew = dhcp_get_option_long(option_ptr + 2);
  465. } else {
  466. /* calculate safe periods for renewal */
  467. dhcp->offered_t1_renew = dhcp->offered_t0_lease / 2;
  468. }
  469. /* renewal period given? */
  470. option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_T2);
  471. if (option_ptr != NULL) {
  472. /* remember given rebind period */
  473. dhcp->offered_t2_rebind = dhcp_get_option_long(option_ptr + 2);
  474. } else {
  475. /* calculate safe periods for rebinding */
  476. dhcp->offered_t2_rebind = dhcp->offered_t0_lease;
  477. }
  478. /* (y)our internet address */
  479. ip_addr_set(&dhcp->offered_ip_addr, &dhcp->msg_in->yiaddr);
  480. /**
  481. * Patch #1308
  482. * TODO: we must check if the file field is not overloaded by DHCP options!
  483. */
  484. #if 0
  485. /* boot server address */
  486. ip_addr_set(&dhcp->offered_si_addr, &dhcp->msg_in->siaddr);
  487. /* boot file name */
  488. if (dhcp->msg_in->file[0]) {
  489. dhcp->boot_file_name = mem_malloc(strlen(dhcp->msg_in->file) + 1);
  490. strcpy(dhcp->boot_file_name, dhcp->msg_in->file);
  491. }
  492. #endif
  493. /* subnet mask */
  494. option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_SUBNET_MASK);
  495. /* subnet mask given? */
  496. if (option_ptr != NULL) {
  497. dhcp->offered_sn_mask.addr = htonl(dhcp_get_option_long(&option_ptr[2]));
  498. }
  499. /* gateway router */
  500. option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_ROUTER);
  501. if (option_ptr != NULL) {
  502. dhcp->offered_gw_addr.addr = htonl(dhcp_get_option_long(&option_ptr[2]));
  503. }
  504. /* broadcast address */
  505. option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_BROADCAST);
  506. if (option_ptr != NULL) {
  507. dhcp->offered_bc_addr.addr = htonl(dhcp_get_option_long(&option_ptr[2]));
  508. }
  509. /* DNS servers */
  510. option_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_DNS_SERVER);
  511. if (option_ptr != NULL) {
  512. u8_t n;
  513. dhcp->dns_count = dhcp_get_option_byte(&option_ptr[1]) / (u32_t)sizeof(struct ip_addr);
  514. /* limit to at most DHCP_MAX_DNS DNS servers */
  515. if (dhcp->dns_count > DHCP_MAX_DNS)
  516. dhcp->dns_count = DHCP_MAX_DNS;
  517. for (n = 0; n < dhcp->dns_count; n++) {
  518. dhcp->offered_dns_addr[n].addr = htonl(dhcp_get_option_long(&option_ptr[2 + n * 4]));
  519. #if LWIP_DNS
  520. dns_setserver( n, (struct ip_addr *)(&(dhcp->offered_dns_addr[n].addr)));
  521. #endif /* LWIP_DNS */
  522. }
  523. #if LWIP_DNS
  524. dns_setserver( n, (struct ip_addr *)(&ip_addr_any));
  525. #endif /* LWIP_DNS */
  526. }
  527. }
  528. /**
  529. * Start DHCP negotiation for a network interface.
  530. *
  531. * If no DHCP client instance was attached to this interface,
  532. * a new client is created first. If a DHCP client instance
  533. * was already present, it restarts negotiation.
  534. *
  535. * @param netif The lwIP network interface
  536. * @return lwIP error code
  537. * - ERR_OK - No error
  538. * - ERR_MEM - Out of memory
  539. */
  540. err_t
  541. dhcp_start(struct netif *netif)
  542. {
  543. struct dhcp *dhcp;
  544. err_t result = ERR_OK;
  545. LWIP_ERROR("netif != NULL", (netif != NULL), return ERR_ARG;);
  546. dhcp = netif->dhcp;
  547. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_start(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
  548. /* Remove the flag that says this netif is handled by DHCP,
  549. it is set when we succeeded starting. */
  550. netif->flags &= ~NETIF_FLAG_DHCP;
  551. /* check MTU of the netif */
  552. if (netif->mtu < DHCP_MAX_MSG_LEN_MIN_REQUIRED) {
  553. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): Cannot use this netif with DHCP: MTU is too small\n"));
  554. return ERR_MEM;
  555. }
  556. /* no DHCP client attached yet? */
  557. if (dhcp == NULL) {
  558. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): starting new DHCP client\n"));
  559. dhcp = mem_malloc(sizeof(struct dhcp));
  560. if (dhcp == NULL) {
  561. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): could not allocate dhcp\n"));
  562. return ERR_MEM;
  563. }
  564. /* store this dhcp client in the netif */
  565. netif->dhcp = dhcp;
  566. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): allocated dhcp"));
  567. /* already has DHCP client attached */
  568. } else {
  569. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_start(): restarting DHCP configuration\n"));
  570. if (dhcp->pcb != NULL) {
  571. udp_remove(dhcp->pcb);
  572. }
  573. LWIP_ASSERT("pbuf p_out wasn't freed", dhcp->p_out == NULL);
  574. LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL &&
  575. dhcp->options_in == NULL && dhcp->options_in_len == 0);
  576. }
  577. /* clear data structure */
  578. memset(dhcp, 0, sizeof(struct dhcp));
  579. /* allocate UDP PCB */
  580. dhcp->pcb = udp_new();
  581. if (dhcp->pcb == NULL) {
  582. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): could not obtain pcb\n"));
  583. mem_free((void *)dhcp);
  584. netif->dhcp = dhcp = NULL;
  585. return ERR_MEM;
  586. }
  587. #if IP_SOF_BROADCAST
  588. dhcp->pcb->so_options|=SOF_BROADCAST;
  589. #endif /* IP_SOF_BROADCAST */
  590. /* set up local and remote port for the pcb */
  591. udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
  592. udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
  593. /* set up the recv callback and argument */
  594. udp_recv(dhcp->pcb, dhcp_recv, netif);
  595. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): starting DHCP configuration\n"));
  596. /* (re)start the DHCP negotiation */
  597. result = dhcp_discover(netif);
  598. if (result != ERR_OK) {
  599. /* free resources allocated above */
  600. dhcp_stop(netif);
  601. return ERR_MEM;
  602. }
  603. /* Set the flag that says this netif is handled by DHCP. */
  604. netif->flags |= NETIF_FLAG_DHCP;
  605. return result;
  606. }
  607. /**
  608. * Inform a DHCP server of our manual configuration.
  609. *
  610. * This informs DHCP servers of our fixed IP address configuration
  611. * by sending an INFORM message. It does not involve DHCP address
  612. * configuration, it is just here to be nice to the network.
  613. *
  614. * @param netif The lwIP network interface
  615. */
  616. void
  617. dhcp_inform(struct netif *netif)
  618. {
  619. struct dhcp *dhcp, *old_dhcp;
  620. err_t result = ERR_OK;
  621. dhcp = mem_malloc(sizeof(struct dhcp));
  622. if (dhcp == NULL) {
  623. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_inform(): could not allocate dhcp\n"));
  624. return;
  625. }
  626. memset(dhcp, 0, sizeof(struct dhcp));
  627. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_inform(): allocated dhcp\n"));
  628. dhcp->pcb = udp_new();
  629. if (dhcp->pcb == NULL) {
  630. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_inform(): could not obtain pcb"));
  631. goto free_dhcp_and_return;
  632. }
  633. old_dhcp = netif->dhcp;
  634. netif->dhcp = dhcp;
  635. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_inform(): created new udp pcb\n"));
  636. /* create and initialize the DHCP message header */
  637. result = dhcp_create_request(netif);
  638. if (result == ERR_OK) {
  639. dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
  640. dhcp_option_byte(dhcp, DHCP_INFORM);
  641. dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
  642. dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif));
  643. dhcp_option_trailer(dhcp);
  644. pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
  645. #if IP_SOF_BROADCAST
  646. dhcp->pcb->so_options|=SOF_BROADCAST;
  647. #endif /* IP_SOF_BROADCAST */
  648. udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
  649. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_inform: INFORMING\n"));
  650. udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
  651. dhcp_delete_request(netif);
  652. } else {
  653. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_inform: could not allocate DHCP request\n"));
  654. }
  655. udp_remove(dhcp->pcb);
  656. dhcp->pcb = NULL;
  657. netif->dhcp = old_dhcp;
  658. free_dhcp_and_return:
  659. mem_free((void *)dhcp);
  660. }
  661. /** Handle a possible change in the network configuration.
  662. *
  663. * This enters the REBOOTING state to verify that the currently bound
  664. * address is still valid.
  665. */
  666. void
  667. dhcp_network_changed(struct netif *netif)
  668. {
  669. struct dhcp *dhcp = netif->dhcp;
  670. if (!dhcp)
  671. return;
  672. switch (dhcp->state) {
  673. case DHCP_REBINDING:
  674. case DHCP_RENEWING:
  675. case DHCP_BOUND:
  676. case DHCP_REBOOTING:
  677. netif_set_down(netif);
  678. dhcp->tries = 0;
  679. dhcp_reboot(netif);
  680. break;
  681. case DHCP_OFF:
  682. /* stay off */
  683. break;
  684. default:
  685. dhcp->tries = 0;
  686. dhcp_discover(netif);
  687. break;
  688. }
  689. }
  690. #if DHCP_DOES_ARP_CHECK
  691. /**
  692. * Match an ARP reply with the offered IP address.
  693. *
  694. * @param netif the network interface on which the reply was received
  695. * @param addr The IP address we received a reply from
  696. */
  697. void dhcp_arp_reply(struct netif *netif, struct ip_addr *addr)
  698. {
  699. LWIP_ERROR("netif != NULL", (netif != NULL), return;);
  700. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_arp_reply()\n"));
  701. /* is a DHCP client doing an ARP check? */
  702. if ((netif->dhcp != NULL) && (netif->dhcp->state == DHCP_CHECKING)) {
  703. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_arp_reply(): CHECKING, arp reply for 0x%08"X32_F"\n", addr->addr));
  704. /* did a host respond with the address we
  705. were offered by the DHCP server? */
  706. if (ip_addr_cmp(addr, &netif->dhcp->offered_ip_addr)) {
  707. /* we will not accept the offered address */
  708. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING,
  709. ("dhcp_arp_reply(): arp reply matched with offered address, declining\n"));
  710. dhcp_decline(netif);
  711. }
  712. }
  713. }
  714. /**
  715. * Decline an offered lease.
  716. *
  717. * Tell the DHCP server we do not accept the offered address.
  718. * One reason to decline the lease is when we find out the address
  719. * is already in use by another host (through ARP).
  720. *
  721. * @param netif the netif under DHCP control
  722. */
  723. static err_t
  724. dhcp_decline(struct netif *netif)
  725. {
  726. struct dhcp *dhcp = netif->dhcp;
  727. err_t result = ERR_OK;
  728. u16_t msecs;
  729. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_decline()\n"));
  730. dhcp_set_state(dhcp, DHCP_BACKING_OFF);
  731. /* create and initialize the DHCP message header */
  732. result = dhcp_create_request(netif);
  733. if (result == ERR_OK) {
  734. dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
  735. dhcp_option_byte(dhcp, DHCP_DECLINE);
  736. dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
  737. dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr));
  738. dhcp_option_trailer(dhcp);
  739. /* resize pbuf to reflect true size of options */
  740. pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
  741. /* per section 4.4.4, broadcast DECLINE messages */
  742. udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
  743. dhcp_delete_request(netif);
  744. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_decline: BACKING OFF\n"));
  745. } else {
  746. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
  747. ("dhcp_decline: could not allocate DHCP request\n"));
  748. }
  749. dhcp->tries++;
  750. msecs = 10*1000;
  751. dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
  752. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_decline(): set request timeout %"U16_F" msecs\n", msecs));
  753. return result;
  754. }
  755. #endif
  756. /**
  757. * Start the DHCP process, discover a DHCP server.
  758. *
  759. * @param netif the netif under DHCP control
  760. */
  761. static err_t
  762. dhcp_discover(struct netif *netif)
  763. {
  764. struct dhcp *dhcp = netif->dhcp;
  765. err_t result = ERR_OK;
  766. u16_t msecs;
  767. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover()\n"));
  768. ip_addr_set(&dhcp->offered_ip_addr, IP_ADDR_ANY);
  769. dhcp_set_state(dhcp, DHCP_SELECTING);
  770. /* create and initialize the DHCP message header */
  771. result = dhcp_create_request(netif);
  772. if (result == ERR_OK) {
  773. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: making request\n"));
  774. dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
  775. dhcp_option_byte(dhcp, DHCP_DISCOVER);
  776. dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
  777. dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif));
  778. dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 4/*num options*/);
  779. dhcp_option_byte(dhcp, DHCP_OPTION_SUBNET_MASK);
  780. dhcp_option_byte(dhcp, DHCP_OPTION_ROUTER);
  781. dhcp_option_byte(dhcp, DHCP_OPTION_BROADCAST);
  782. dhcp_option_byte(dhcp, DHCP_OPTION_DNS_SERVER);
  783. dhcp_option_trailer(dhcp);
  784. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: realloc()ing\n"));
  785. pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
  786. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, DHCP_SERVER_PORT)\n"));
  787. udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
  788. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: deleting()ing\n"));
  789. dhcp_delete_request(netif);
  790. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover: SELECTING\n"));
  791. } else {
  792. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_discover: could not allocate DHCP request\n"));
  793. }
  794. dhcp->tries++;
  795. #if LWIP_DHCP_AUTOIP_COOP
  796. if(dhcp->tries >= LWIP_DHCP_AUTOIP_COOP_TRIES && dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_OFF) {
  797. dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_ON;
  798. autoip_start(netif);
  799. }
  800. #endif /* LWIP_DHCP_AUTOIP_COOP */
  801. msecs = (dhcp->tries < 6 ? 1 << dhcp->tries : 60) * 1000;
  802. dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
  803. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover(): set request timeout %"U16_F" msecs\n", msecs));
  804. return result;
  805. }
  806. /**
  807. * Bind the interface to the offered IP address.
  808. *
  809. * @param netif network interface to bind to the offered address
  810. */
  811. static void
  812. dhcp_bind(struct netif *netif)
  813. {
  814. u32_t timeout;
  815. struct dhcp *dhcp;
  816. struct ip_addr sn_mask, gw_addr;
  817. LWIP_ERROR("dhcp_bind: netif != NULL", (netif != NULL), return;);
  818. dhcp = netif->dhcp;
  819. LWIP_ERROR("dhcp_bind: dhcp != NULL", (dhcp != NULL), return;);
  820. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
  821. /* temporary DHCP lease? */
  822. if (dhcp->offered_t1_renew != 0xffffffffUL) {
  823. /* set renewal period timer */
  824. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t1 renewal timer %"U32_F" secs\n", dhcp->offered_t1_renew));
  825. timeout = (dhcp->offered_t1_renew + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS;
  826. if(timeout > 0xffff) {
  827. timeout = 0xffff;
  828. }
  829. dhcp->t1_timeout = (u16_t)timeout;
  830. if (dhcp->t1_timeout == 0) {
  831. dhcp->t1_timeout = 1;
  832. }
  833. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t1_renew*1000));
  834. }
  835. /* set renewal period timer */
  836. if (dhcp->offered_t2_rebind != 0xffffffffUL) {
  837. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t2 rebind timer %"U32_F" secs\n", dhcp->offered_t2_rebind));
  838. timeout = (dhcp->offered_t2_rebind + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS;
  839. if(timeout > 0xffff) {
  840. timeout = 0xffff;
  841. }
  842. dhcp->t2_timeout = (u16_t)timeout;
  843. if (dhcp->t2_timeout == 0) {
  844. dhcp->t2_timeout = 1;
  845. }
  846. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t2_rebind*1000));
  847. }
  848. /* copy offered network mask */
  849. ip_addr_set(&sn_mask, &dhcp->offered_sn_mask);
  850. /* subnet mask not given? */
  851. /* TODO: this is not a valid check. what if the network mask is 0? */
  852. if (sn_mask.addr == 0) {
  853. /* choose a safe subnet mask given the network class */
  854. u8_t first_octet = ip4_addr1(&sn_mask);
  855. if (first_octet <= 127) {
  856. sn_mask.addr = htonl(0xff000000);
  857. } else if (first_octet >= 192) {
  858. sn_mask.addr = htonl(0xffffff00);
  859. } else {
  860. sn_mask.addr = htonl(0xffff0000);
  861. }
  862. }
  863. ip_addr_set(&gw_addr, &dhcp->offered_gw_addr);
  864. /* gateway address not given? */
  865. if (gw_addr.addr == 0) {
  866. /* copy network address */
  867. gw_addr.addr = (dhcp->offered_ip_addr.addr & sn_mask.addr);
  868. /* use first host address on network as gateway */
  869. gw_addr.addr |= htonl(0x00000001);
  870. }
  871. #if LWIP_DHCP_AUTOIP_COOP
  872. if(dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) {
  873. autoip_stop(netif);
  874. dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF;
  875. }
  876. #endif /* LWIP_DHCP_AUTOIP_COOP */
  877. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): IP: 0x%08"X32_F"\n", dhcp->offered_ip_addr.addr));
  878. netif_set_ipaddr(netif, &dhcp->offered_ip_addr);
  879. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): SN: 0x%08"X32_F"\n", sn_mask.addr));
  880. netif_set_netmask(netif, &sn_mask);
  881. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): GW: 0x%08"X32_F"\n", gw_addr.addr));
  882. netif_set_gw(netif, &gw_addr);
  883. /* bring the interface up */
  884. netif_set_up(netif);
  885. /* netif is now bound to DHCP leased address */
  886. dhcp_set_state(dhcp, DHCP_BOUND);
  887. }
  888. /**
  889. * Renew an existing DHCP lease at the involved DHCP server.
  890. *
  891. * @param netif network interface which must renew its lease
  892. */
  893. err_t
  894. dhcp_renew(struct netif *netif)
  895. {
  896. struct dhcp *dhcp = netif->dhcp;
  897. err_t result;
  898. u16_t msecs;
  899. #if LWIP_NETIF_HOSTNAME
  900. const char *p;
  901. #endif /* LWIP_NETIF_HOSTNAME */
  902. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_renew()\n"));
  903. dhcp_set_state(dhcp, DHCP_RENEWING);
  904. /* create and initialize the DHCP message header */
  905. result = dhcp_create_request(netif);
  906. if (result == ERR_OK) {
  907. dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
  908. dhcp_option_byte(dhcp, DHCP_REQUEST);
  909. dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
  910. dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif));
  911. #if LWIP_NETIF_HOSTNAME
  912. p = (const char*)netif->hostname;
  913. if (p != NULL) {
  914. dhcp_option(dhcp, DHCP_OPTION_HOSTNAME, strlen(p));
  915. while (*p) {
  916. dhcp_option_byte(dhcp, *p++);
  917. }
  918. }
  919. #endif /* LWIP_NETIF_HOSTNAME */
  920. #if 0
  921. dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
  922. dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr));
  923. #endif
  924. #if 0
  925. dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4);
  926. dhcp_option_long(dhcp, ntohl(dhcp->server_ip_addr.addr));
  927. #endif
  928. /* append DHCP message trailer */
  929. dhcp_option_trailer(dhcp);
  930. pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
  931. udp_sendto_if(dhcp->pcb, dhcp->p_out, &dhcp->server_ip_addr, DHCP_SERVER_PORT, netif);
  932. dhcp_delete_request(netif);
  933. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_renew: RENEWING\n"));
  934. } else {
  935. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_renew: could not allocate DHCP request\n"));
  936. }
  937. dhcp->tries++;
  938. /* back-off on retries, but to a maximum of 20 seconds */
  939. msecs = dhcp->tries < 10 ? dhcp->tries * 2000 : 20 * 1000;
  940. dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
  941. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_renew(): set request timeout %"U16_F" msecs\n", msecs));
  942. return result;
  943. }
  944. /**
  945. * Rebind with a DHCP server for an existing DHCP lease.
  946. *
  947. * @param netif network interface which must rebind with a DHCP server
  948. */
  949. static err_t
  950. dhcp_rebind(struct netif *netif)
  951. {
  952. struct dhcp *dhcp = netif->dhcp;
  953. err_t result;
  954. u16_t msecs;
  955. #if LWIP_NETIF_HOSTNAME
  956. const char *p;
  957. #endif /* LWIP_NETIF_HOSTNAME */
  958. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind()\n"));
  959. dhcp_set_state(dhcp, DHCP_REBINDING);
  960. /* create and initialize the DHCP message header */
  961. result = dhcp_create_request(netif);
  962. if (result == ERR_OK) {
  963. dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
  964. dhcp_option_byte(dhcp, DHCP_REQUEST);
  965. dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
  966. dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif));
  967. #if LWIP_NETIF_HOSTNAME
  968. p = (const char*)netif->hostname;
  969. if (p != NULL) {
  970. dhcp_option(dhcp, DHCP_OPTION_HOSTNAME, strlen(p));
  971. while (*p) {
  972. dhcp_option_byte(dhcp, *p++);
  973. }
  974. }
  975. #endif /* LWIP_NETIF_HOSTNAME */
  976. #if 0
  977. dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
  978. dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr));
  979. dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4);
  980. dhcp_option_long(dhcp, ntohl(dhcp->server_ip_addr.addr));
  981. #endif
  982. dhcp_option_trailer(dhcp);
  983. pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
  984. /* broadcast to server */
  985. udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
  986. dhcp_delete_request(netif);
  987. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind: REBINDING\n"));
  988. } else {
  989. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_rebind: could not allocate DHCP request\n"));
  990. }
  991. dhcp->tries++;
  992. msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000;
  993. dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
  994. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind(): set request timeout %"U16_F" msecs\n", msecs));
  995. return result;
  996. }
  997. /**
  998. * Enter REBOOTING state to verify an existing lease
  999. *
  1000. * @param netif network interface which must reboot
  1001. */
  1002. static err_t
  1003. dhcp_reboot(struct netif *netif)
  1004. {
  1005. struct dhcp *dhcp = netif->dhcp;
  1006. err_t result;
  1007. u16_t msecs;
  1008. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot()\n"));
  1009. dhcp_set_state(dhcp, DHCP_REBOOTING);
  1010. /* create and initialize the DHCP message header */
  1011. result = dhcp_create_request(netif);
  1012. if (result == ERR_OK) {
  1013. dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
  1014. dhcp_option_byte(dhcp, DHCP_REQUEST);
  1015. dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
  1016. dhcp_option_short(dhcp, 576);
  1017. dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
  1018. dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr));
  1019. dhcp_option_trailer(dhcp);
  1020. pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
  1021. /* broadcast to server */
  1022. udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
  1023. dhcp_delete_request(netif);
  1024. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot: REBOOTING\n"));
  1025. } else {
  1026. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_reboot: could not allocate DHCP request\n"));
  1027. }
  1028. dhcp->tries++;
  1029. msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000;
  1030. dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
  1031. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot(): set request timeout %"U16_F" msecs\n", msecs));
  1032. return result;
  1033. }
  1034. /**
  1035. * Release a DHCP lease.
  1036. *
  1037. * @param netif network interface which must release its lease
  1038. */
  1039. err_t
  1040. dhcp_release(struct netif *netif)
  1041. {
  1042. struct dhcp *dhcp = netif->dhcp;
  1043. err_t result;
  1044. u16_t msecs;
  1045. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_release()\n"));
  1046. /* idle DHCP client */
  1047. dhcp_set_state(dhcp, DHCP_OFF);
  1048. /* clean old DHCP offer */
  1049. dhcp->server_ip_addr.addr = 0;
  1050. dhcp->offered_ip_addr.addr = dhcp->offered_sn_mask.addr = 0;
  1051. dhcp->offered_gw_addr.addr = dhcp->offered_bc_addr.addr = 0;
  1052. dhcp->offered_t0_lease = dhcp->offered_t1_renew = dhcp->offered_t2_rebind = 0;
  1053. dhcp->dns_count = 0;
  1054. /* create and initialize the DHCP message header */
  1055. result = dhcp_create_request(netif);
  1056. if (result == ERR_OK) {
  1057. dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
  1058. dhcp_option_byte(dhcp, DHCP_RELEASE);
  1059. dhcp_option_trailer(dhcp);
  1060. pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
  1061. udp_sendto_if(dhcp->pcb, dhcp->p_out, &dhcp->server_ip_addr, DHCP_SERVER_PORT, netif);
  1062. dhcp_delete_request(netif);
  1063. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_release: RELEASED, DHCP_OFF\n"));
  1064. } else {
  1065. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_release: could not allocate DHCP request\n"));
  1066. }
  1067. dhcp->tries++;
  1068. msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000;
  1069. dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
  1070. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_release(): set request timeout %"U16_F" msecs\n", msecs));
  1071. /* bring the interface down */
  1072. netif_set_down(netif);
  1073. /* remove IP address from interface */
  1074. netif_set_ipaddr(netif, IP_ADDR_ANY);
  1075. netif_set_gw(netif, IP_ADDR_ANY);
  1076. netif_set_netmask(netif, IP_ADDR_ANY);
  1077. /* TODO: netif_down(netif); */
  1078. return result;
  1079. }
  1080. /**
  1081. * Remove the DHCP client from the interface.
  1082. *
  1083. * @param netif The network interface to stop DHCP on
  1084. */
  1085. void
  1086. dhcp_stop(struct netif *netif)
  1087. {
  1088. struct dhcp *dhcp = netif->dhcp;
  1089. LWIP_ERROR("dhcp_stop: netif != NULL", (netif != NULL), return;);
  1090. /* Remove the flag that says this netif is handled by DHCP. */
  1091. netif->flags &= ~NETIF_FLAG_DHCP;
  1092. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_stop()\n"));
  1093. /* netif is DHCP configured? */
  1094. if (dhcp != NULL) {
  1095. #if LWIP_DHCP_AUTOIP_COOP
  1096. if(dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) {
  1097. autoip_stop(netif);
  1098. dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF;
  1099. }
  1100. #endif /* LWIP_DHCP_AUTOIP_COOP */
  1101. if (dhcp->pcb != NULL) {
  1102. udp_remove(dhcp->pcb);
  1103. dhcp->pcb = NULL;
  1104. }
  1105. LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL &&
  1106. dhcp->options_in == NULL && dhcp->options_in_len == 0);
  1107. mem_free((void *)dhcp);
  1108. netif->dhcp = NULL;
  1109. }
  1110. }
  1111. /*
  1112. * Set the DHCP state of a DHCP client.
  1113. *
  1114. * If the state changed, reset the number of tries.
  1115. *
  1116. * TODO: we might also want to reset the timeout here?
  1117. */
  1118. static void
  1119. dhcp_set_state(struct dhcp *dhcp, u8_t new_state)
  1120. {
  1121. if (new_state != dhcp->state) {
  1122. dhcp->state = new_state;
  1123. dhcp->tries = 0;
  1124. }
  1125. }
  1126. /*
  1127. * Concatenate an option type and length field to the outgoing
  1128. * DHCP message.
  1129. *
  1130. */
  1131. static void
  1132. dhcp_option(struct dhcp *dhcp, u8_t option_type, u8_t option_len)
  1133. {
  1134. LWIP_ASSERT("dhcp_option: dhcp->options_out_len + 2 + option_len <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 2U + option_len <= DHCP_OPTIONS_LEN);
  1135. dhcp->msg_out->options[dhcp->options_out_len++] = option_type;
  1136. dhcp->msg_out->options[dhcp->options_out_len++] = option_len;
  1137. }
  1138. /*
  1139. * Concatenate a single byte to the outgoing DHCP message.
  1140. *
  1141. */
  1142. static void
  1143. dhcp_option_byte(struct dhcp *dhcp, u8_t value)
  1144. {
  1145. LWIP_ASSERT("dhcp_option_byte: dhcp->options_out_len < DHCP_OPTIONS_LEN", dhcp->options_out_len < DHCP_OPTIONS_LEN);
  1146. dhcp->msg_out->options[dhcp->options_out_len++] = value;
  1147. }
  1148. static void
  1149. dhcp_option_short(struct dhcp *dhcp, u16_t value)
  1150. {
  1151. LWIP_ASSERT("dhcp_option_short: dhcp->options_out_len + 2 <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 2U <= DHCP_OPTIONS_LEN);
  1152. dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0xff00U) >> 8);
  1153. dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t) (value & 0x00ffU);
  1154. }
  1155. static void
  1156. dhcp_option_long(struct dhcp *dhcp, u32_t value)
  1157. {
  1158. LWIP_ASSERT("dhcp_option_long: dhcp->options_out_len + 4 <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 4U <= DHCP_OPTIONS_LEN);
  1159. dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0xff000000UL) >> 24);
  1160. dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x00ff0000UL) >> 16);
  1161. dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x0000ff00UL) >> 8);
  1162. dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x000000ffUL));
  1163. }
  1164. /**
  1165. * Extract the DHCP message and the DHCP options.
  1166. *
  1167. * Extract the DHCP message and the DHCP options, each into a contiguous
  1168. * piece of memory. As a DHCP message is variable sized by its options,
  1169. * and also allows overriding some fields for options, the easy approach
  1170. * is to first unfold the options into a conitguous piece of memory, and
  1171. * use that further on.
  1172. *
  1173. */
  1174. static err_t
  1175. dhcp_unfold_reply(struct dhcp *dhcp, struct pbuf *p)
  1176. {
  1177. u16_t ret;
  1178. LWIP_ERROR("dhcp != NULL", (dhcp != NULL), return ERR_ARG;);
  1179. /* free any left-overs from previous unfolds */
  1180. dhcp_free_reply(dhcp);
  1181. /* options present? */
  1182. if (p->tot_len > (sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN)) {
  1183. dhcp->options_in_len = p->tot_len - (sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN);
  1184. dhcp->options_in = mem_malloc(dhcp->options_in_len);
  1185. if (dhcp->options_in == NULL) {
  1186. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
  1187. ("dhcp_unfold_reply(): could not allocate dhcp->options\n"));
  1188. dhcp->options_in_len = 0;
  1189. return ERR_MEM;
  1190. }
  1191. }
  1192. dhcp->msg_in = mem_malloc(sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN);
  1193. if (dhcp->msg_in == NULL) {
  1194. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
  1195. ("dhcp_unfold_reply(): could not allocate dhcp->msg_in\n"));
  1196. if (dhcp->options_in != NULL) {
  1197. mem_free(dhcp->options_in);
  1198. dhcp->options_in = NULL;
  1199. dhcp->options_in_len = 0;
  1200. }
  1201. return ERR_MEM;
  1202. }
  1203. /** copy the DHCP message without options */
  1204. ret = pbuf_copy_partial(p, dhcp->msg_in, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN, 0);
  1205. LWIP_ASSERT("ret == sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN", ret == sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN);
  1206. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_unfold_reply(): copied %"U16_F" bytes into dhcp->msg_in[]\n",
  1207. sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN));
  1208. if (dhcp->options_in != NULL) {
  1209. /** copy the DHCP options */
  1210. ret = pbuf_copy_partial(p, dhcp->options_in, dhcp->options_in_len, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN);
  1211. LWIP_ASSERT("ret == dhcp->options_in_len", ret == dhcp->options_in_len);
  1212. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_unfold_reply(): copied %"U16_F" bytes to dhcp->options_in[]\n",
  1213. dhcp->options_in_len));
  1214. }
  1215. LWIP_UNUSED_ARG(ret);
  1216. return ERR_OK;
  1217. }
  1218. /**
  1219. * Free the incoming DHCP message including contiguous copy of
  1220. * its DHCP options.
  1221. */
  1222. static void dhcp_free_reply(struct dhcp *dhcp)
  1223. {
  1224. if (dhcp->msg_in != NULL) {
  1225. mem_free((void *)dhcp->msg_in);
  1226. dhcp->msg_in = NULL;
  1227. }
  1228. if (dhcp->options_in) {
  1229. mem_free(dhcp->options_in);
  1230. dhcp->options_in = NULL;
  1231. dhcp->options_in_len = 0;
  1232. }
  1233. LWIP_DEBUGF(DHCP_DEBUG, ("dhcp_free_reply(): free'd\n"));
  1234. }
  1235. /**
  1236. * If an incoming DHCP message is in response to us, then trigger the state machine
  1237. */
  1238. static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port)
  1239. {
  1240. struct netif *netif = (struct netif *)arg;
  1241. struct dhcp *dhcp = netif->dhcp;
  1242. struct dhcp_msg *reply_msg = (struct dhcp_msg *)p->payload;
  1243. u8_t *options_ptr;
  1244. u8_t msg_type;
  1245. u8_t i;
  1246. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_recv(pbuf = %p) from DHCP server %"U16_F".%"U16_F".%"U16_F".%"U16_F" port %"U16_F"\n", (void*)p,
  1247. (u16_t)(ntohl(addr->addr) >> 24 & 0xff), (u16_t)(ntohl(addr->addr) >> 16 & 0xff),
  1248. (u16_t)(ntohl(addr->addr) >> 8 & 0xff), (u16_t)(ntohl(addr->addr) & 0xff), port));
  1249. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("pbuf->len = %"U16_F"\n", p->len));
  1250. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("pbuf->tot_len = %"U16_F"\n", p->tot_len));
  1251. /* prevent warnings about unused arguments */
  1252. LWIP_UNUSED_ARG(pcb);
  1253. LWIP_UNUSED_ARG(addr);
  1254. LWIP_UNUSED_ARG(port);
  1255. LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL &&
  1256. dhcp->options_in == NULL && dhcp->options_in_len == 0);
  1257. if (p->len < DHCP_MIN_REPLY_LEN) {
  1258. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("DHCP reply message too short\n"));
  1259. goto free_pbuf_and_return;
  1260. }
  1261. if (reply_msg->op != DHCP_BOOTREPLY) {
  1262. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("not a DHCP reply message, but type %"U16_F"\n", (u16_t)reply_msg->op));
  1263. goto free_pbuf_and_return;
  1264. }
  1265. /* iterate through hardware address and match against DHCP message */
  1266. for (i = 0; i < netif->hwaddr_len; i++) {
  1267. if (netif->hwaddr[i] != reply_msg->chaddr[i]) {
  1268. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
  1269. ("netif->hwaddr[%"U16_F"]==%02"X16_F" != reply_msg->chaddr[%"U16_F"]==%02"X16_F"\n",
  1270. (u16_t)i, (u16_t)netif->hwaddr[i], (u16_t)i, (u16_t)reply_msg->chaddr[i]));
  1271. goto free_pbuf_and_return;
  1272. }
  1273. }
  1274. /* match transaction ID against what we expected */
  1275. if (ntohl(reply_msg->xid) != dhcp->xid) {
  1276. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
  1277. ("transaction id mismatch reply_msg->xid(%"X32_F")!=dhcp->xid(%"X32_F")\n",ntohl(reply_msg->xid),dhcp->xid));
  1278. goto free_pbuf_and_return;
  1279. }
  1280. /* option fields could be unfold? */
  1281. if (dhcp_unfold_reply(dhcp, p) != ERR_OK) {
  1282. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
  1283. ("problem unfolding DHCP message - too short on memory?\n"));
  1284. goto free_pbuf_and_return;
  1285. }
  1286. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("searching DHCP_OPTION_MESSAGE_TYPE\n"));
  1287. /* obtain pointer to DHCP message type */
  1288. options_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_MESSAGE_TYPE);
  1289. if (options_ptr == NULL) {
  1290. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("DHCP_OPTION_MESSAGE_TYPE option not found\n"));
  1291. goto free_pbuf_and_return;
  1292. }
  1293. /* read DHCP message type */
  1294. msg_type = dhcp_get_option_byte(options_ptr + 2);
  1295. /* message type is DHCP ACK? */
  1296. if (msg_type == DHCP_ACK) {
  1297. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_ACK received\n"));
  1298. /* in requesting state? */
  1299. if (dhcp->state == DHCP_REQUESTING) {
  1300. dhcp_handle_ack(netif);
  1301. dhcp->request_timeout = 0;
  1302. #if DHCP_DOES_ARP_CHECK
  1303. /* check if the acknowledged lease address is already in use */
  1304. dhcp_check(netif);
  1305. #else
  1306. /* bind interface to the acknowledged lease address */
  1307. dhcp_bind(netif);
  1308. #endif
  1309. }
  1310. /* already bound to the given lease address? */
  1311. else if ((dhcp->state == DHCP_REBOOTING) || (dhcp->state == DHCP_REBINDING) || (dhcp->state == DHCP_RENEWING)) {
  1312. dhcp->request_timeout = 0;
  1313. dhcp_bind(netif);
  1314. }
  1315. }
  1316. /* received a DHCP_NAK in appropriate state? */
  1317. else if ((msg_type == DHCP_NAK) &&
  1318. ((dhcp->state == DHCP_REBOOTING) || (dhcp->state == DHCP_REQUESTING) ||
  1319. (dhcp->state == DHCP_REBINDING) || (dhcp->state == DHCP_RENEWING ))) {
  1320. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_NAK received\n"));
  1321. dhcp->request_timeout = 0;
  1322. dhcp_handle_nak(netif);
  1323. }
  1324. /* received a DHCP_OFFER in DHCP_SELECTING state? */
  1325. else if ((msg_type == DHCP_OFFER) && (dhcp->state == DHCP_SELECTING)) {
  1326. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_OFFER received in DHCP_SELECTING state\n"));
  1327. dhcp->request_timeout = 0;
  1328. /* remember offered lease */
  1329. dhcp_handle_offer(netif);
  1330. }
  1331. free_pbuf_and_return:
  1332. dhcp_free_reply(dhcp);
  1333. pbuf_free(p);
  1334. }
  1335. /**
  1336. * Create a DHCP request, fill in common headers
  1337. *
  1338. * @param netif the netif under DHCP control
  1339. */
  1340. static err_t
  1341. dhcp_create_request(struct netif *netif)
  1342. {
  1343. struct dhcp *dhcp;
  1344. u16_t i;
  1345. #ifndef DHCP_GLOBAL_XID
  1346. /** default global transaction identifier starting value (easy to match
  1347. * with a packet analyser). We simply increment for each new request.
  1348. * Predefine DHCP_GLOBAL_XID to a better value or a function call to generate one
  1349. * at runtime, any supporting function prototypes can be defined in DHCP_GLOBAL_XID_HEADER */
  1350. static u32_t xid = 0xABCD0000;
  1351. #else
  1352. static u32_t xid;
  1353. static u8_t xid_initialised = 0;
  1354. if (!xid_initialised) {
  1355. xid = DHCP_GLOBAL_XID;
  1356. xid_initialised = !xid_initialised;
  1357. }
  1358. #endif
  1359. LWIP_ERROR("dhcp_create_request: netif != NULL", (netif != NULL), return ERR_ARG;);
  1360. dhcp = netif->dhcp;
  1361. LWIP_ERROR("dhcp_create_request: dhcp != NULL", (dhcp != NULL), return ERR_VAL;);
  1362. LWIP_ASSERT("dhcp_create_request: dhcp->p_out == NULL", dhcp->p_out == NULL);
  1363. LWIP_ASSERT("dhcp_create_request: dhcp->msg_out == NULL", dhcp->msg_out == NULL);
  1364. dhcp->p_out = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcp_msg), PBUF_RAM);
  1365. if (dhcp->p_out == NULL) {
  1366. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
  1367. ("dhcp_create_request(): could not allocate pbuf\n"));
  1368. return ERR_MEM;
  1369. }
  1370. LWIP_ASSERT("dhcp_create_request: check that first pbuf can hold struct dhcp_msg",
  1371. (dhcp->p_out->len >= sizeof(struct dhcp_msg)));
  1372. /* reuse transaction identifier in retransmissions */
  1373. if (dhcp->tries==0)
  1374. xid++;
  1375. dhcp->xid = xid;
  1376. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
  1377. ("transaction id xid(%"X32_F")\n", xid));
  1378. dhcp->msg_out = (struct dhcp_msg *)dhcp->p_out->payload;
  1379. dhcp->msg_out->op = DHCP_BOOTREQUEST;
  1380. /* TODO: make link layer independent */
  1381. dhcp->msg_out->htype = DHCP_HTYPE_ETH;
  1382. /* TODO: make link layer independent */
  1383. dhcp->msg_out->hlen = DHCP_HLEN_ETH;
  1384. dhcp->msg_out->hops = 0;
  1385. dhcp->msg_out->xid = htonl(dhcp->xid);
  1386. dhcp->msg_out->secs = 0;
  1387. dhcp->msg_out->flags = 0;
  1388. dhcp->msg_out->ciaddr.addr = 0;
  1389. if (dhcp->state==DHCP_BOUND || dhcp->state==DHCP_RENEWING || dhcp->state==DHCP_REBINDING) {
  1390. dhcp->msg_out->ciaddr.addr = netif->ip_addr.addr;
  1391. }
  1392. dhcp->msg_out->yiaddr.addr = 0;
  1393. dhcp->msg_out->siaddr.addr = 0;
  1394. dhcp->msg_out->giaddr.addr = 0;
  1395. for (i = 0; i < DHCP_CHADDR_LEN; i++) {
  1396. /* copy netif hardware address, pad with zeroes */
  1397. dhcp->msg_out->chaddr[i] = (i < netif->hwaddr_len) ? netif->hwaddr[i] : 0/* pad byte*/;
  1398. }
  1399. for (i = 0; i < DHCP_SNAME_LEN; i++) {
  1400. dhcp->msg_out->sname[i] = 0;
  1401. }
  1402. for (i = 0; i < DHCP_FILE_LEN; i++) {
  1403. dhcp->msg_out->file[i] = 0;
  1404. }
  1405. dhcp->msg_out->cookie = htonl(0x63825363UL);
  1406. dhcp->options_out_len = 0;
  1407. /* fill options field with an incrementing array (for debugging purposes) */
  1408. for (i = 0; i < DHCP_OPTIONS_LEN; i++) {
  1409. dhcp->msg_out->options[i] = (u8_t)i; /* for debugging only, no matter if truncated */
  1410. }
  1411. return ERR_OK;
  1412. }
  1413. /**
  1414. * Free previously allocated memory used to send a DHCP request.
  1415. *
  1416. * @param netif the netif under DHCP control
  1417. */
  1418. static void
  1419. dhcp_delete_request(struct netif *netif)
  1420. {
  1421. struct dhcp *dhcp;
  1422. LWIP_ERROR("dhcp_delete_request: netif != NULL", (netif != NULL), return;);
  1423. dhcp = netif->dhcp;
  1424. LWIP_ERROR("dhcp_delete_request: dhcp != NULL", (dhcp != NULL), return;);
  1425. LWIP_ASSERT("dhcp_delete_request: dhcp->p_out != NULL", dhcp->p_out != NULL);
  1426. LWIP_ASSERT("dhcp_delete_request: dhcp->msg_out != NULL", dhcp->msg_out != NULL);
  1427. if (dhcp->p_out != NULL) {
  1428. pbuf_free(dhcp->p_out);
  1429. }
  1430. dhcp->p_out = NULL;
  1431. dhcp->msg_out = NULL;
  1432. }
  1433. /**
  1434. * Add a DHCP message trailer
  1435. *
  1436. * Adds the END option to the DHCP message, and if
  1437. * necessary, up to three padding bytes.
  1438. *
  1439. * @param dhcp DHCP state structure
  1440. */
  1441. static void
  1442. dhcp_option_trailer(struct dhcp *dhcp)
  1443. {
  1444. LWIP_ERROR("dhcp_option_trailer: dhcp != NULL", (dhcp != NULL), return;);
  1445. LWIP_ASSERT("dhcp_option_trailer: dhcp->msg_out != NULL\n", dhcp->msg_out != NULL);
  1446. LWIP_ASSERT("dhcp_option_trailer: dhcp->options_out_len < DHCP_OPTIONS_LEN\n", dhcp->options_out_len < DHCP_OPTIONS_LEN);
  1447. dhcp->msg_out->options[dhcp->options_out_len++] = DHCP_OPTION_END;
  1448. /* packet is too small, or not 4 byte aligned? */
  1449. while ((dhcp->options_out_len < DHCP_MIN_OPTIONS_LEN) || (dhcp->options_out_len & 3)) {
  1450. /* LWIP_DEBUGF(DHCP_DEBUG,("dhcp_option_trailer:dhcp->options_out_len=%"U16_F", DHCP_OPTIONS_LEN=%"U16_F, dhcp->options_out_len, DHCP_OPTIONS_LEN)); */
  1451. LWIP_ASSERT("dhcp_option_trailer: dhcp->options_out_len < DHCP_OPTIONS_LEN\n", dhcp->options_out_len < DHCP_OPTIONS_LEN);
  1452. /* add a fill/padding byte */
  1453. dhcp->msg_out->options[dhcp->options_out_len++] = 0;
  1454. }
  1455. }
  1456. /**
  1457. * Find the offset of a DHCP option inside the DHCP message.
  1458. *
  1459. * @param dhcp DHCP client
  1460. * @param option_type
  1461. *
  1462. * @return a byte offset into the UDP message where the option was found, or
  1463. * zero if the given option was not found.
  1464. */
  1465. static u8_t *dhcp_get_option_ptr(struct dhcp *dhcp, u8_t option_type)
  1466. {
  1467. u8_t overload = DHCP_OVERLOAD_NONE;
  1468. /* options available? */
  1469. if ((dhcp->options_in != NULL) && (dhcp->options_in_len > 0)) {
  1470. /* start with options field */
  1471. u8_t *options = (u8_t *)dhcp->options_in;
  1472. u16_t offset = 0;
  1473. /* at least 1 byte to read and no end marker, then at least 3 bytes to read? */
  1474. while ((offset < dhcp->options_in_len) && (options[offset] != DHCP_OPTION_END)) {
  1475. /* LWIP_DEBUGF(DHCP_DEBUG, ("msg_offset=%"U16_F", q->len=%"U16_F, msg_offset, q->len)); */
  1476. /* are the sname and/or file field overloaded with options? */
  1477. if (options[offset] == DHCP_OPTION_OVERLOAD) {
  1478. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded message detected\n"));
  1479. /* skip option type and length */
  1480. offset += 2;
  1481. overload = options[offset++];
  1482. }
  1483. /* requested option found */
  1484. else if (options[offset] == option_type) {
  1485. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("option found at offset %"U16_F" in options\n", offset));
  1486. return &options[offset];
  1487. /* skip option */
  1488. } else {
  1489. LWIP_DEBUGF(DHCP_DEBUG, ("skipping option %"U16_F" in options\n", options[offset]));
  1490. /* skip option type */
  1491. offset++;
  1492. /* skip option length, and then length bytes */
  1493. offset += 1 + options[offset];
  1494. }
  1495. }
  1496. /* is this an overloaded message? */
  1497. if (overload != DHCP_OVERLOAD_NONE) {
  1498. u16_t field_len;
  1499. if (overload == DHCP_OVERLOAD_FILE) {
  1500. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded file field\n"));
  1501. options = (u8_t *)&dhcp->msg_in->file;
  1502. field_len = DHCP_FILE_LEN;
  1503. } else if (overload == DHCP_OVERLOAD_SNAME) {
  1504. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded sname field\n"));
  1505. options = (u8_t *)&dhcp->msg_in->sname;
  1506. field_len = DHCP_SNAME_LEN;
  1507. /* TODO: check if else if () is necessary */
  1508. } else {
  1509. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded sname and file field\n"));
  1510. options = (u8_t *)&dhcp->msg_in->sname;
  1511. field_len = DHCP_FILE_LEN + DHCP_SNAME_LEN;
  1512. }
  1513. offset = 0;
  1514. /* at least 1 byte to read and no end marker */
  1515. while ((offset < field_len) && (options[offset] != DHCP_OPTION_END)) {
  1516. if (options[offset] == option_type) {
  1517. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("option found at offset=%"U16_F"\n", offset));
  1518. return &options[offset];
  1519. /* skip option */
  1520. } else {
  1521. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("skipping option %"U16_F"\n", options[offset]));
  1522. /* skip option type */
  1523. offset++;
  1524. offset += 1 + options[offset];
  1525. }
  1526. }
  1527. }
  1528. }
  1529. return NULL;
  1530. }
  1531. /**
  1532. * Return the byte of DHCP option data.
  1533. *
  1534. * @param client DHCP client.
  1535. * @param ptr pointer obtained by dhcp_get_option_ptr().
  1536. *
  1537. * @return byte value at the given address.
  1538. */
  1539. static u8_t
  1540. dhcp_get_option_byte(u8_t *ptr)
  1541. {
  1542. LWIP_DEBUGF(DHCP_DEBUG, ("option byte value=%"U16_F"\n", (u16_t)(*ptr)));
  1543. return *ptr;
  1544. }
  1545. #if 0 /* currently unused */
  1546. /**
  1547. * Return the 16-bit value of DHCP option data.
  1548. *
  1549. * @param client DHCP client.
  1550. * @param ptr pointer obtained by dhcp_get_option_ptr().
  1551. *
  1552. * @return byte value at the given address.
  1553. */
  1554. static u16_t
  1555. dhcp_get_option_short(u8_t *ptr)
  1556. {
  1557. u16_t value;
  1558. value = *ptr++ << 8;
  1559. value |= *ptr;
  1560. LWIP_DEBUGF(DHCP_DEBUG, ("option short value=%"U16_F"\n", value));
  1561. return value;
  1562. }
  1563. #endif
  1564. /**
  1565. * Return the 32-bit value of DHCP option data.
  1566. *
  1567. * @param client DHCP client.
  1568. * @param ptr pointer obtained by dhcp_get_option_ptr().
  1569. *
  1570. * @return byte value at the given address.
  1571. */
  1572. static u32_t dhcp_get_option_long(u8_t *ptr)
  1573. {
  1574. u32_t value;
  1575. value = (u32_t)(*ptr++) << 24;
  1576. value |= (u32_t)(*ptr++) << 16;
  1577. value |= (u32_t)(*ptr++) << 8;
  1578. value |= (u32_t)(*ptr++);
  1579. LWIP_DEBUGF(DHCP_DEBUG, ("option long value=%"U32_F"\n", value));
  1580. return value;
  1581. }
  1582. #endif /* LWIP_DHCP */