1 /**
2 * @file
3 * Dynamic Host Configuration Protocol client
4 *
5 * @defgroup dhcp4 DHCPv4
6 * @ingroup ip4
7 * DHCP (IPv4) related functions
8 * This is a DHCP client for the lwIP TCP/IP stack. It aims to conform
9 * with RFC 2131 and RFC 2132.
10 *
11 * @todo:
12 * - Support for interfaces other than Ethernet (SLIP, PPP, ...)
13 *
14 * Options:
15 * @ref DHCP_COARSE_TIMER_SECS (recommended 60 which is a minute)
16 * @ref DHCP_FINE_TIMER_MSECS (recommended 500 which equals TCP coarse timer)
17 *
18 * dhcp_start() starts a DHCP client instance which
19 * configures the interface by obtaining an IP address lease and maintaining it.
20 *
21 * Use dhcp_release() to end the lease and use dhcp_stop()
22 * to remove the DHCP client.
23 *
24 * @see netifapi_dhcp4
25 */
26
27 /*
28 * Copyright (c) 2001-2004 Leon Woestenberg <leon.woestenberg@gmx.net>
29 * Copyright (c) 2001-2004 Axon Digital Design B.V., The Netherlands.
30 * All rights reserved.
31 *
32 * Redistribution and use in source and binary forms, with or without modification,
33 * are permitted provided that the following conditions are met:
34 *
35 * 1. Redistributions of source code must retain the above copyright notice,
36 * this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright notice,
38 * this list of conditions and the following disclaimer in the documentation
39 * and/or other materials provided with the distribution.
40 * 3. The name of the author may not be used to endorse or promote products
41 * derived from this software without specific prior written permission.
42 *
43 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
44 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
45 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
46 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
47 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
48 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
49 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
50 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
51 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
52 * OF SUCH DAMAGE.
53 *
54 * This file is part of the lwIP TCP/IP stack.
55 * The Swedish Institute of Computer Science and Adam Dunkels
56 * are specifically granted permission to redistribute this
57 * source code.
58 *
59 * Author: Leon Woestenberg <leon.woestenberg@gmx.net>
60 *
61 */
62
63 #include "lwip/opt.h"
64
65 #if LWIP_IPV4 && LWIP_DHCP /* don't build if not configured for use in lwipopts.h */
66
67 #include "lwip/stats.h"
68 #include "lwip/mem.h"
69 #include "lwip/udp.h"
70 #include "lwip/ip_addr.h"
71 #include "lwip/netif.h"
72 #include "lwip/def.h"
73 #include "lwip/dhcp.h"
74 #include "lwip/autoip.h"
75 #include "lwip/dns.h"
76 #include "lwip/etharp.h"
77 #include "lwip/prot/dhcp.h"
78
79 #ifdef FEATURE_UND_SUPPORT
80 #include "und/und.h"
81 #endif
82
83 #include <string.h>
84
85 /** DHCP_CREATE_RAND_XID: if this is set to 1, the xid is created using
86 * LWIP_RAND() (this overrides DHCP_GLOBAL_XID)
87 */
88 #ifndef DHCP_CREATE_RAND_XID
89 #define DHCP_CREATE_RAND_XID 1
90 #endif
91
92 /** Default for DHCP_GLOBAL_XID is 0xABCD0000
93 * This can be changed by defining DHCP_GLOBAL_XID and DHCP_GLOBAL_XID_HEADER, e.g.
94 * \#define DHCP_GLOBAL_XID_HEADER "stdlib.h"
95 * \#define DHCP_GLOBAL_XID rand()
96 */
97 #ifdef DHCP_GLOBAL_XID_HEADER
98 #include DHCP_GLOBAL_XID_HEADER /* include optional starting XID generation prototypes */
99 #endif
100
101 /** DHCP_OPTION_MAX_MSG_SIZE is set to the MTU
102 * MTU is checked to be big enough in dhcp_start */
103 #define DHCP_MAX_MSG_LEN(netif) (netif->mtu)
104 #define DHCP_MAX_MSG_LEN_MIN_REQUIRED 576
105 /** Minimum length for reply before packet is parsed */
106 #define DHCP_MIN_REPLY_LEN 44
107
108 #define REBOOT_TRIES 2
109
110 /** Option handling: options are parsed in dhcp_parse_reply
111 * and saved in an array where other functions can load them from.
112 * This might be moved into the struct dhcp (not necessarily since
113 * lwIP is single-threaded and the array is only used while in recv
114 * callback). */
115 #define DHCP_OPTION_IDX_OVERLOAD 0
116 #define DHCP_OPTION_IDX_MSG_TYPE 1
117 #define DHCP_OPTION_IDX_SERVER_ID 2
118 #define DHCP_OPTION_IDX_LEASE_TIME 3
119 #define DHCP_OPTION_IDX_T1 4
120 #define DHCP_OPTION_IDX_T2 5
121 #define DHCP_OPTION_IDX_SUBNET_MASK 6
122 #define DHCP_OPTION_IDX_ROUTER 7
123 #define DHCP_OPTION_IDX_DNS_SERVER 8
124 #if LWIP_DHCP_GET_NTP_SRV
125 #define DHCP_OPTION_IDX_NTP_SERVER (DHCP_OPTION_IDX_DNS_SERVER + DNS_MAX_SERVERS)
126 #define DHCP_OPTION_IDX_MAX (DHCP_OPTION_IDX_NTP_SERVER + LWIP_DHCP_MAX_NTP_SERVERS)
127 #else /* LWIP_DHCP_GET_NTP_SRV */
128 #define DHCP_OPTION_IDX_MAX (DHCP_OPTION_IDX_DNS_SERVER + DNS_MAX_SERVERS)
129 #endif /* LWIP_DHCP_GET_NTP_SRV */
130
131 /** Holds the decoded option values, only valid while in dhcp_recv.
132 @todo: move this into struct dhcp? */
133 u32_t dhcp_rx_options_val[DHCP_OPTION_IDX_MAX];
134 /** Holds a flag which option was received and is contained in dhcp_rx_options_val,
135 only valid while in dhcp_recv.
136 @todo: move this into struct dhcp? */
137 u8_t dhcp_rx_options_given[DHCP_OPTION_IDX_MAX];
138
139 static u8_t dhcp_discover_request_options[] = {
140 DHCP_OPTION_SUBNET_MASK,
141 DHCP_OPTION_ROUTER,
142 DHCP_OPTION_BROADCAST,
143 DHCP_OPTION_DNS_SERVER
144 #if LWIP_DHCP_GET_NTP_SRV
145 , DHCP_OPTION_NTP
146 #endif /* LWIP_DHCP_GET_NTP_SRV */
147 };
148
149 #ifdef DHCP_GLOBAL_XID
150 static u32_t xid;
151 static u8_t xid_initialised;
152 #endif /* DHCP_GLOBAL_XID */
153
154 #define dhcp_option_given(dhcp, idx) (dhcp_rx_options_given[idx] != 0)
155 #define dhcp_got_option(dhcp, idx) (dhcp_rx_options_given[idx] = 1)
156 #define dhcp_clear_option(dhcp, idx) (dhcp_rx_options_given[idx] = 0)
157 #define dhcp_clear_all_options(dhcp) (memset(dhcp_rx_options_given, 0, sizeof(dhcp_rx_options_given)))
158 #define dhcp_get_option_value(dhcp, idx) (dhcp_rx_options_val[idx])
159 #define dhcp_set_option_value(dhcp, idx, val) (dhcp_rx_options_val[idx] = (val))
160
161 static struct udp_pcb *dhcp_pcb;
162 static u8_t dhcp_pcb_refcount;
163
164 #if DHCP_TIMEOUT_WORKAROUND_FOR_BK_WIFI
165 static u8_t dhcp_timeout_reboot = 0;
166 #endif
167
168 /* DHCP client state machine functions */
169 static err_t dhcp_discover(struct netif *netif);
170 static err_t dhcp_select(struct netif *netif);
171 static void dhcp_bind(struct netif *netif);
172 #if DHCP_DOES_ARP_CHECK
173 static err_t dhcp_decline(struct netif *netif);
174 #endif /* DHCP_DOES_ARP_CHECK */
175 static err_t dhcp_rebind(struct netif *netif);
176 static err_t dhcp_reboot(struct netif *netif);
177 static void dhcp_set_state(struct dhcp *dhcp, u8_t new_state);
178
179 /* receive, unfold, parse and free incoming messages */
180 static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port);
181
182 /* set the DHCP timers */
183 static void dhcp_timeout(struct netif *netif);
184 static void dhcp_t1_timeout(struct netif *netif);
185 static void dhcp_t2_timeout(struct netif *netif);
186
187 /* build outgoing messages */
188 /* create a DHCP message, fill in common headers */
189 static err_t dhcp_create_msg(struct netif *netif, struct dhcp *dhcp, u8_t message_type);
190 /* free a DHCP request */
191 static void dhcp_delete_msg(struct dhcp *dhcp);
192 /* add a DHCP option (type, then length in bytes) */
193 static void dhcp_option(struct dhcp *dhcp, u8_t option_type, u8_t option_len);
194 /* add option values */
195 static void dhcp_option_byte(struct dhcp *dhcp, u8_t value);
196 static void dhcp_option_short(struct dhcp *dhcp, u16_t value);
197 static void dhcp_option_long(struct dhcp *dhcp, u32_t value);
198 #if LWIP_NETIF_HOSTNAME
199 static void dhcp_option_hostname(struct dhcp *dhcp, struct netif *netif);
200 #endif /* LWIP_NETIF_HOSTNAME */
201 /* always add the DHCP options trailer to end and pad */
202 static void dhcp_option_trailer(struct dhcp *dhcp);
203
204 /** Ensure DHCP PCB is allocated and bound */
205 static err_t
dhcp_inc_pcb_refcount(void)206 dhcp_inc_pcb_refcount(void)
207 {
208 if (dhcp_pcb_refcount == 0) {
209 LWIP_ASSERT("dhcp_inc_pcb_refcount(): memory leak", dhcp_pcb == NULL);
210
211 /* allocate UDP PCB */
212 dhcp_pcb = udp_new();
213
214 if (dhcp_pcb == NULL) {
215 return ERR_MEM;
216 }
217
218 ip_set_option(dhcp_pcb, SOF_BROADCAST);
219
220 /* set up local and remote port for the pcb -> listen on all interfaces on all src/dest IPs */
221 udp_bind(dhcp_pcb, IP4_ADDR_ANY, DHCP_CLIENT_PORT);
222 udp_connect(dhcp_pcb, IP4_ADDR_ANY, DHCP_SERVER_PORT);
223 udp_recv(dhcp_pcb, dhcp_recv, NULL);
224 }
225
226 dhcp_pcb_refcount++;
227
228 return ERR_OK;
229 }
230
231 /** Free DHCP PCB if the last netif stops using it */
232 static void
dhcp_dec_pcb_refcount(void)233 dhcp_dec_pcb_refcount(void)
234 {
235 LWIP_ASSERT("dhcp_pcb_refcount(): refcount error", (dhcp_pcb_refcount > 0));
236 dhcp_pcb_refcount--;
237
238 if (dhcp_pcb_refcount == 0) {
239 udp_remove(dhcp_pcb);
240 dhcp_pcb = NULL;
241 }
242 }
243
244 /**
245 * Back-off the DHCP client (because of a received NAK response).
246 *
247 * Back-off the DHCP client because of a received NAK. Receiving a
248 * NAK means the client asked for something non-sensible, for
249 * example when it tries to renew a lease obtained on another network.
250 *
251 * We clear any existing set IP address and restart DHCP negotiation
252 * afresh (as per RFC2131 3.2.3).
253 *
254 * @param netif the netif under DHCP control
255 */
256 static void
dhcp_handle_nak(struct netif * netif)257 dhcp_handle_nak(struct netif *netif)
258 {
259 struct dhcp *dhcp = netif_dhcp_data(netif);
260
261 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_handle_nak(netif=%p) %c%c%"U16_F"\n",
262 (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
263 /* Change to a defined state - set this before assigning the address
264 to ensure the callback can use dhcp_supplied_address() */
265 dhcp_set_state(dhcp, DHCP_STATE_BACKING_OFF);
266 /* remove IP address from interface (must no longer be used, as per RFC2131) */
267 netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4);
268 /* We can immediately restart discovery */
269 dhcp_discover(netif);
270 }
271
272 #if DHCP_DOES_ARP_CHECK
273 /**
274 * Checks if the offered IP address is already in use.
275 *
276 * It does so by sending an ARP request for the offered address and
277 * entering CHECKING state. If no ARP reply is received within a small
278 * interval, the address is assumed to be free for use by us.
279 *
280 * @param netif the netif under DHCP control
281 */
282 static void
dhcp_check(struct netif * netif)283 dhcp_check(struct netif *netif)
284 {
285 struct dhcp *dhcp = netif_dhcp_data(netif);
286 err_t result;
287 u16_t msecs;
288 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_check(netif=%p) %c%c\n", (void *)netif, (s16_t)netif->name[0],
289 (s16_t)netif->name[1]));
290 dhcp_set_state(dhcp, DHCP_STATE_CHECKING);
291 /* create an ARP query for the offered IP address, expecting that no host
292 responds, as the IP address should not be in use. */
293 result = etharp_query(netif, &dhcp->offered_ip_addr, NULL);
294 if (result != ERR_OK) {
295 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("dhcp_check: could not perform ARP query\n"));
296 }
297 if (dhcp->tries < 255) {
298 dhcp->tries++;
299 }
300 msecs = 500;
301 dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
302 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_check(): set request timeout %"U16_F" msecs\n", msecs));
303 }
304 #endif /* DHCP_DOES_ARP_CHECK */
305
306 /**
307 * Remember the configuration offered by a DHCP server.
308 *
309 * @param netif the netif under DHCP control
310 */
311 static void
dhcp_handle_offer(struct netif * netif)312 dhcp_handle_offer(struct netif *netif)
313 {
314 struct dhcp *dhcp = netif_dhcp_data(netif);
315
316 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_handle_offer(netif=%p) %c%c%"U16_F"\n",
317 (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
318 /* obtain the server address */
319 if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_SERVER_ID)) {
320 ip_addr_set_ip4_u32(&dhcp->server_ip_addr, lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_SERVER_ID)));
321 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_handle_offer(): server 0x%08"X32_F"\n",
322 ip4_addr_get_u32(ip_2_ip4(&dhcp->server_ip_addr))));
323 /* remember offered address */
324 ip4_addr_copy(dhcp->offered_ip_addr, dhcp->msg_in->yiaddr);
325 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_handle_offer(): offer for 0x%08"X32_F"\n",
326 ip4_addr_get_u32(&dhcp->offered_ip_addr)));
327
328 dhcp_select(netif);
329 } else {
330 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
331 ("dhcp_handle_offer(netif=%p) did not get server ID!\n", (void*)netif));
332 }
333 }
334
335 /**
336 * Select a DHCP server offer out of all offers.
337 *
338 * Simply select the first offer received.
339 *
340 * @param netif the netif under DHCP control
341 * @return lwIP specific error (see error.h)
342 */
343 static err_t
dhcp_select(struct netif * netif)344 dhcp_select(struct netif *netif)
345 {
346 struct dhcp *dhcp = netif_dhcp_data(netif);
347 err_t result;
348 u16_t msecs;
349 u8_t i;
350
351 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));
352 dhcp_set_state(dhcp, DHCP_STATE_REQUESTING);
353
354 /* create and initialize the DHCP message header */
355 result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST);
356 if (result == ERR_OK) {
357 dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
358 dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif));
359
360 /* MUST request the offered IP address */
361 dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
362 dhcp_option_long(dhcp, lwip_ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr)));
363
364 dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4);
365 dhcp_option_long(dhcp, lwip_ntohl(ip4_addr_get_u32(ip_2_ip4(&dhcp->server_ip_addr))));
366
367 dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, LWIP_ARRAYSIZE(dhcp_discover_request_options));
368 for (i = 0; i < LWIP_ARRAYSIZE(dhcp_discover_request_options); i++) {
369 dhcp_option_byte(dhcp, dhcp_discover_request_options[i]);
370 }
371
372 #if LWIP_NETIF_HOSTNAME
373 dhcp_option_hostname(dhcp, netif);
374 #endif /* LWIP_NETIF_HOSTNAME */
375
376 dhcp_option_trailer(dhcp);
377 /* shrink the pbuf to the actual content length */
378 pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
379
380 /* send broadcast to any DHCP server */
381 udp_sendto_if_src(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif, IP4_ADDR_ANY);
382 dhcp_delete_msg(dhcp);
383 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_select: REQUESTING\n"));
384 } else {
385 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("dhcp_select: could not allocate DHCP request\n"));
386 }
387 if (dhcp->tries < 255) {
388 dhcp->tries++;
389 }
390 msecs = (dhcp->tries < 6 ? 1 << dhcp->tries : 60) * 1000;
391 dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
392 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_select(): set request timeout %"U16_F" msecs\n", msecs));
393 return result;
394 }
395
396 /**
397 * The DHCP timer that checks for lease renewal/rebind timeouts.
398 * Must be called once a minute (see @ref DHCP_COARSE_TIMER_SECS).
399 */
400 void
dhcp_coarse_tmr(void)401 dhcp_coarse_tmr(void)
402 {
403 struct netif *netif = netif_list;
404 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_coarse_tmr()\n"));
405 /* iterate through all network interfaces */
406 while (netif != NULL) {
407 /* only act on DHCP configured interfaces */
408 struct dhcp *dhcp = netif_dhcp_data(netif);
409 if ((dhcp != NULL) && (dhcp->state != DHCP_STATE_OFF)) {
410 /* compare lease time to expire timeout */
411 if (dhcp->t0_timeout && (++dhcp->lease_used == dhcp->t0_timeout)) {
412 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_coarse_tmr(): t0 timeout\n"));
413 /* this clients' lease time has expired */
414 dhcp_release(netif);
415 dhcp_discover(netif);
416 /* timer is active (non zero), and triggers (zeroes) now? */
417 } else if (dhcp->t2_rebind_time && (dhcp->t2_rebind_time-- == 1)) {
418 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_coarse_tmr(): t2 timeout\n"));
419 /* this clients' rebind timeout triggered */
420 dhcp_t2_timeout(netif);
421 /* timer is active (non zero), and triggers (zeroes) now */
422 } else if (dhcp->t1_renew_time && (dhcp->t1_renew_time-- == 1)) {
423 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_coarse_tmr(): t1 timeout\n"));
424 /* this clients' renewal timeout triggered */
425 dhcp_t1_timeout(netif);
426 }
427 }
428 /* proceed to next netif */
429 netif = netif->next;
430 }
431 }
432
433 /**
434 * DHCP transaction timeout handling (this function must be called every 500ms,
435 * see @ref DHCP_FINE_TIMER_MSECS).
436 *
437 * A DHCP server is expected to respond within a short period of time.
438 * This timer checks whether an outstanding DHCP request is timed out.
439 */
440 void
dhcp_fine_tmr(void)441 dhcp_fine_tmr(void)
442 {
443 struct netif *netif = netif_list;
444 /* loop through netif's */
445 while (netif != NULL) {
446 struct dhcp *dhcp = netif_dhcp_data(netif);
447 /* only act on DHCP configured interfaces */
448 if (dhcp != NULL) {
449 /* timer is active (non zero), and is about to trigger now */
450 if (dhcp->request_timeout > 1) {
451 dhcp->request_timeout--;
452 }
453 else if (dhcp->request_timeout == 1) {
454 dhcp->request_timeout--;
455 /* { netif->dhcp->request_timeout == 0 } */
456 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_fine_tmr(): request timeout\n"));
457 /* this client's request timeout triggered */
458 dhcp_timeout(netif);
459 }
460 }
461 /* proceed to next network interface */
462 netif = netif->next;
463 }
464 }
465
466 /**
467 * A DHCP negotiation transaction, or ARP request, has timed out.
468 *
469 * The timer that was started with the DHCP or ARP request has
470 * timed out, indicating no response was received in time.
471 *
472 * @param netif the netif under DHCP control
473 */
474 static void
dhcp_timeout(struct netif * netif)475 dhcp_timeout(struct netif *netif)
476 {
477 struct dhcp *dhcp = netif_dhcp_data(netif);
478
479 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_timeout()\n"));
480 /* back-off period has passed, or server selection timed out */
481 if ((dhcp->state == DHCP_STATE_BACKING_OFF) || (dhcp->state == DHCP_STATE_SELECTING)) {
482 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_timeout(): restarting discovery\n"));
483 dhcp_discover(netif);
484 /* receiving the requested lease timed out */
485 } else if (dhcp->state == DHCP_STATE_REQUESTING) {
486 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): REQUESTING, DHCP request timed out\n"));
487 if (dhcp->tries <= 5) {
488 dhcp_select(netif);
489 } else {
490 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): REQUESTING, releasing, restarting\n"));
491 dhcp_release(netif);
492 dhcp_discover(netif);
493 }
494 #if DHCP_DOES_ARP_CHECK
495 /* received no ARP reply for the offered address (which is good) */
496 } else if (dhcp->state == DHCP_STATE_CHECKING) {
497 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): CHECKING, ARP request timed out\n"));
498 if (dhcp->tries <= 1) {
499 dhcp_check(netif);
500 /* no ARP replies on the offered address,
501 looks like the IP address is indeed free */
502 } else {
503 /* bind the interface to the offered address */
504 dhcp_bind(netif);
505 }
506 #endif /* DHCP_DOES_ARP_CHECK */
507 } else if (dhcp->state == DHCP_STATE_REBOOTING) {
508 if (dhcp->tries < REBOOT_TRIES) {
509 dhcp_reboot(netif);
510 } else {
511 dhcp_discover(netif);
512 }
513 }
514 }
515
516 /**
517 * The renewal period has timed out.
518 *
519 * @param netif the netif under DHCP control
520 */
521 static void
dhcp_t1_timeout(struct netif * netif)522 dhcp_t1_timeout(struct netif *netif)
523 {
524 struct dhcp *dhcp = netif_dhcp_data(netif);
525
526 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_t1_timeout()\n"));
527 if ((dhcp->state == DHCP_STATE_REQUESTING) || (dhcp->state == DHCP_STATE_BOUND) ||
528 (dhcp->state == DHCP_STATE_RENEWING)) {
529 /* just retry to renew - note that the rebind timer (t2) will
530 * eventually time-out if renew tries fail. */
531 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
532 ("dhcp_t1_timeout(): must renew\n"));
533 /* This slightly different to RFC2131: DHCPREQUEST will be sent from state
534 DHCP_STATE_RENEWING, not DHCP_STATE_BOUND */
535 dhcp_renew(netif);
536 /* Calculate next timeout */
537 if (((dhcp->t2_timeout - dhcp->lease_used) / 2) >= ((60 + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS))
538 {
539 dhcp->t1_renew_time = ((dhcp->t2_timeout - dhcp->lease_used) / 2);
540 }
541 }
542 }
543
544 /**
545 * The rebind period has timed out.
546 *
547 * @param netif the netif under DHCP control
548 */
549 static void
dhcp_t2_timeout(struct netif * netif)550 dhcp_t2_timeout(struct netif *netif)
551 {
552 struct dhcp *dhcp = netif_dhcp_data(netif);
553
554 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_t2_timeout()\n"));
555 if ((dhcp->state == DHCP_STATE_REQUESTING) || (dhcp->state == DHCP_STATE_BOUND) ||
556 (dhcp->state == DHCP_STATE_RENEWING) || (dhcp->state == DHCP_STATE_REBINDING)) {
557 /* just retry to rebind */
558 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
559 ("dhcp_t2_timeout(): must rebind\n"));
560 /* This slightly different to RFC2131: DHCPREQUEST will be sent from state
561 DHCP_STATE_REBINDING, not DHCP_STATE_BOUND */
562 dhcp_rebind(netif);
563 /* Calculate next timeout */
564 if (((dhcp->t0_timeout - dhcp->lease_used) / 2) >= ((60 + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS))
565 {
566 dhcp->t2_rebind_time = ((dhcp->t0_timeout - dhcp->lease_used) / 2);
567 }
568 }
569 }
570
571 /**
572 * Handle a DHCP ACK packet
573 *
574 * @param netif the netif under DHCP control
575 */
576 static void
dhcp_handle_ack(struct netif * netif)577 dhcp_handle_ack(struct netif *netif)
578 {
579 struct dhcp *dhcp = netif_dhcp_data(netif);
580
581 #if LWIP_DNS || LWIP_DHCP_GET_NTP_SRV
582 u8_t n;
583 #endif /* LWIP_DNS || LWIP_DHCP_GET_NTP_SRV */
584 #if LWIP_DHCP_GET_NTP_SRV
585 ip4_addr_t ntp_server_addrs[LWIP_DHCP_MAX_NTP_SERVERS];
586 #endif
587
588 /* clear options we might not get from the ACK */
589 ip4_addr_set_zero(&dhcp->offered_sn_mask);
590 ip4_addr_set_zero(&dhcp->offered_gw_addr);
591 #if LWIP_DHCP_BOOTP_FILE
592 ip4_addr_set_zero(&dhcp->offered_si_addr);
593 #endif /* LWIP_DHCP_BOOTP_FILE */
594
595 /* lease time given? */
596 if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_LEASE_TIME)) {
597 /* remember offered lease time */
598 dhcp->offered_t0_lease = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_LEASE_TIME);
599 }
600 /* renewal period given? */
601 if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_T1)) {
602 /* remember given renewal period */
603 dhcp->offered_t1_renew = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_T1);
604 } else {
605 /* calculate safe periods for renewal */
606 dhcp->offered_t1_renew = dhcp->offered_t0_lease / 2;
607 }
608
609 /* renewal period given? */
610 if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_T2)) {
611 /* remember given rebind period */
612 dhcp->offered_t2_rebind = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_T2);
613 } else {
614 /* calculate safe periods for rebinding (offered_t0_lease * 0.875 -> 87.5%)*/
615 dhcp->offered_t2_rebind = (dhcp->offered_t0_lease * 7U) / 8U;
616 }
617
618 /* (y)our internet address */
619 ip4_addr_copy(dhcp->offered_ip_addr, dhcp->msg_in->yiaddr);
620
621 #if LWIP_DHCP_BOOTP_FILE
622 /* copy boot server address,
623 boot file name copied in dhcp_parse_reply if not overloaded */
624 ip4_addr_copy(dhcp->offered_si_addr, dhcp->msg_in->siaddr);
625 #endif /* LWIP_DHCP_BOOTP_FILE */
626
627 /* subnet mask given? */
628 if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_SUBNET_MASK)) {
629 /* remember given subnet mask */
630 ip4_addr_set_u32(&dhcp->offered_sn_mask, lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_SUBNET_MASK)));
631 dhcp->subnet_mask_given = 1;
632 } else {
633 dhcp->subnet_mask_given = 0;
634 }
635
636 /* gateway router */
637 if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_ROUTER)) {
638 ip4_addr_set_u32(&dhcp->offered_gw_addr, lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_ROUTER)));
639 }
640
641 #if LWIP_DHCP_GET_NTP_SRV
642 /* NTP servers */
643 for (n = 0; (n < LWIP_DHCP_MAX_NTP_SERVERS) && dhcp_option_given(dhcp, DHCP_OPTION_IDX_NTP_SERVER + n); n++) {
644 ip4_addr_set_u32(&ntp_server_addrs[n], lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_NTP_SERVER + n)));
645 }
646 dhcp_set_ntp_servers(n, ntp_server_addrs);
647 #endif /* LWIP_DHCP_GET_NTP_SRV */
648
649 #if LWIP_DNS
650 /* DNS servers */
651 for (n = 0; (n < DNS_MAX_SERVERS) && dhcp_option_given(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n); n++) {
652 ip_addr_t dns_addr;
653 ip_addr_set_ip4_u32(&dns_addr, lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n)));
654 dns_setserver(n, &dns_addr);
655 }
656 #endif /* LWIP_DNS */
657 }
658
659 /**
660 * @ingroup dhcp4
661 * Set a statically allocated struct dhcp to work with.
662 * Using this prevents dhcp_start to allocate it using mem_malloc.
663 *
664 * @param netif the netif for which to set the struct dhcp
665 * @param dhcp (uninitialised) dhcp struct allocated by the application
666 */
667 void
dhcp_set_struct(struct netif * netif,struct dhcp * dhcp)668 dhcp_set_struct(struct netif *netif, struct dhcp *dhcp)
669 {
670 LWIP_ASSERT("netif != NULL", netif != NULL);
671 LWIP_ASSERT("dhcp != NULL", dhcp != NULL);
672 LWIP_ASSERT("netif already has a struct dhcp set", netif_dhcp_data(netif) == NULL);
673
674 /* clear data structure */
675 memset(dhcp, 0, sizeof(struct dhcp));
676 /* dhcp_set_state(&dhcp, DHCP_STATE_OFF); */
677 netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP, dhcp);
678 }
679
680 /**
681 * @ingroup dhcp4
682 * Removes a struct dhcp from a netif.
683 *
684 * ATTENTION: Only use this when not using dhcp_set_struct() to allocate the
685 * struct dhcp since the memory is passed back to the heap.
686 *
687 * @param netif the netif from which to remove the struct dhcp
688 */
dhcp_cleanup(struct netif * netif)689 void dhcp_cleanup(struct netif *netif)
690 {
691 LWIP_ASSERT("netif != NULL", netif != NULL);
692
693 if (netif_dhcp_data(netif) != NULL) {
694 mem_free(netif_dhcp_data(netif));
695 netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP, NULL);
696 }
697 }
698
699 /**
700 * @ingroup dhcp4
701 * Start DHCP negotiation for a network interface.
702 *
703 * If no DHCP client instance was attached to this interface,
704 * a new client is created first. If a DHCP client instance
705 * was already present, it restarts negotiation.
706 *
707 * @param netif The lwIP network interface
708 * @return lwIP error code
709 * - ERR_OK - No error
710 * - ERR_MEM - Out of memory
711 */
712 err_t
dhcp_start(struct netif * netif)713 dhcp_start(struct netif *netif)
714 {
715 struct dhcp *dhcp;
716 err_t result;
717
718 LWIP_ERROR("netif != NULL", (netif != NULL), return ERR_ARG;);
719 LWIP_ERROR("netif is not up, old style port?", netif_is_up(netif), return ERR_ARG;);
720 dhcp = netif_dhcp_data(netif);
721 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));
722
723 /* check MTU of the netif */
724 if (netif->mtu < DHCP_MAX_MSG_LEN_MIN_REQUIRED) {
725 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): Cannot use this netif with DHCP: MTU is too small\n"));
726 #ifdef FEATURE_UND_SUPPORT
727 und_update_statis(UND_STATIS_NETWORK_FAIL_IDX, UND_STATIS_NETWORK_DHCP_FAIL_REASON);
728 #endif
729 return ERR_MEM;
730 }
731
732 /* no DHCP client attached yet? */
733 if (dhcp == NULL) {
734 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): starting new DHCP client\n"));
735 dhcp = (struct dhcp *)mem_malloc(sizeof(struct dhcp));
736 if (dhcp == NULL) {
737 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): could not allocate dhcp\n"));
738 #ifdef FEATURE_UND_SUPPORT
739 und_update_statis(UND_STATIS_NETWORK_FAIL_IDX, UND_STATIS_NETWORK_DHCP_FAIL_REASON);
740 #endif
741 return ERR_MEM;
742 }
743
744 /* store this dhcp client in the netif */
745 netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP, dhcp);
746 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): allocated dhcp"));
747 /* already has DHCP client attached */
748 } else {
749 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_start(): restarting DHCP configuration\n"));
750 LWIP_ASSERT("pbuf p_out wasn't freed", dhcp->p_out == NULL);
751 LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL );
752
753 if (dhcp->pcb_allocated != 0) {
754 dhcp_dec_pcb_refcount(); /* free DHCP PCB if not needed any more */
755 }
756 /* dhcp is cleared below, no need to reset flag*/
757 }
758
759 /* clear data structure */
760 memset(dhcp, 0, sizeof(struct dhcp));
761 /* dhcp_set_state(&dhcp, DHCP_STATE_OFF); */
762
763 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): starting DHCP configuration\n"));
764
765 if (dhcp_inc_pcb_refcount() != ERR_OK) { /* ensure DHCP PCB is allocated */
766 #ifdef FEATURE_UND_SUPPORT
767 und_update_statis(UND_STATIS_NETWORK_FAIL_IDX, UND_STATIS_NETWORK_DHCP_FAIL_REASON);
768 #endif
769 return ERR_MEM;
770 }
771 dhcp->pcb_allocated = 1;
772
773 #if LWIP_DHCP_CHECK_LINK_UP
774 if (!netif_is_link_up(netif)) {
775 /* set state INIT and wait for dhcp_network_changed() to call dhcp_discover() */
776 dhcp_set_state(dhcp, DHCP_STATE_INIT);
777 return ERR_OK;
778 }
779 #endif /* LWIP_DHCP_CHECK_LINK_UP */
780
781
782 /* (re)start the DHCP negotiation */
783 result = dhcp_discover(netif);
784 if (result != ERR_OK) {
785 /* free resources allocated above */
786 #ifdef FEATURE_UND_SUPPORT
787 und_update_statis(UND_STATIS_NETWORK_FAIL_IDX, UND_STATIS_NETWORK_DHCP_FAIL_REASON);
788 #endif
789 dhcp_stop(netif);
790 return ERR_MEM;
791 }
792
793 #if DHCP_TIMEOUT_WORKAROUND_FOR_BK_WIFI
794 dhcp_start_timeout_check(DHCP_TIMER_TIMEOUT);
795 #endif
796
797 return result;
798 }
799
800 /**
801 * @ingroup dhcp4
802 * Inform a DHCP server of our manual configuration.
803 *
804 * This informs DHCP servers of our fixed IP address configuration
805 * by sending an INFORM message. It does not involve DHCP address
806 * configuration, it is just here to be nice to the network.
807 *
808 * @param netif The lwIP network interface
809 */
810 void
dhcp_inform(struct netif * netif)811 dhcp_inform(struct netif *netif)
812 {
813 struct dhcp dhcp;
814 err_t result = ERR_OK;
815
816 LWIP_ERROR("netif != NULL", (netif != NULL), return;);
817
818 if (dhcp_inc_pcb_refcount() != ERR_OK) { /* ensure DHCP PCB is allocated */
819 return;
820 }
821
822 memset(&dhcp, 0, sizeof(struct dhcp));
823 dhcp_set_state(&dhcp, DHCP_STATE_INFORMING);
824
825 /* create and initialize the DHCP message header */
826 result = dhcp_create_msg(netif, &dhcp, DHCP_INFORM);
827 if (result == ERR_OK) {
828 dhcp_option(&dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
829 dhcp_option_short(&dhcp, DHCP_MAX_MSG_LEN(netif));
830
831 dhcp_option_trailer(&dhcp);
832
833 pbuf_realloc(dhcp.p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp.options_out_len);
834
835 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_inform: INFORMING\n"));
836
837 udp_sendto_if(dhcp_pcb, dhcp.p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
838
839 dhcp_delete_msg(&dhcp);
840 } else {
841 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_inform: could not allocate DHCP request\n"));
842 }
843
844 dhcp_dec_pcb_refcount(); /* delete DHCP PCB if not needed any more */
845 }
846
847 /** Handle a possible change in the network configuration.
848 *
849 * This enters the REBOOTING state to verify that the currently bound
850 * address is still valid.
851 */
852 void
dhcp_network_changed(struct netif * netif)853 dhcp_network_changed(struct netif *netif)
854 {
855 struct dhcp *dhcp = netif_dhcp_data(netif);
856
857 if (!dhcp)
858 return;
859 switch (dhcp->state) {
860 case DHCP_STATE_REBINDING:
861 case DHCP_STATE_RENEWING:
862 case DHCP_STATE_BOUND:
863 case DHCP_STATE_REBOOTING:
864 dhcp->tries = 0;
865 dhcp_reboot(netif);
866 break;
867 case DHCP_STATE_OFF:
868 /* stay off */
869 break;
870 default:
871 /* INIT/REQUESTING/CHECKING/BACKING_OFF restart with new 'rid' because the
872 state changes, SELECTING: continue with current 'rid' as we stay in the
873 same state */
874 #if LWIP_DHCP_AUTOIP_COOP
875 if (dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) {
876 autoip_stop(netif);
877 dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF;
878 }
879 #endif /* LWIP_DHCP_AUTOIP_COOP */
880 /* ensure we start with short timeouts, even if already discovering */
881 dhcp->tries = 0;
882 dhcp_discover(netif);
883 break;
884 }
885 }
886
887 #if DHCP_DOES_ARP_CHECK
888 /**
889 * Match an ARP reply with the offered IP address:
890 * check whether the offered IP address is not in use using ARP
891 *
892 * @param netif the network interface on which the reply was received
893 * @param addr The IP address we received a reply from
894 */
895 void
dhcp_arp_reply(struct netif * netif,const ip4_addr_t * addr)896 dhcp_arp_reply(struct netif *netif, const ip4_addr_t *addr)
897 {
898 struct dhcp *dhcp;
899
900 LWIP_ERROR("netif != NULL", (netif != NULL), return;);
901 dhcp = netif_dhcp_data(netif);
902 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_arp_reply()\n"));
903 /* is a DHCP client doing an ARP check? */
904 if ((dhcp != NULL) && (dhcp->state == DHCP_STATE_CHECKING)) {
905 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_arp_reply(): CHECKING, arp reply for 0x%08"X32_F"\n",
906 ip4_addr_get_u32(addr)));
907 /* did a host respond with the address we
908 were offered by the DHCP server? */
909 if (ip4_addr_cmp(addr, &dhcp->offered_ip_addr)) {
910 /* we will not accept the offered address */
911 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING,
912 ("dhcp_arp_reply(): arp reply matched with offered address, declining\n"));
913 dhcp_decline(netif);
914 }
915 }
916 }
917
918 /**
919 * Decline an offered lease.
920 *
921 * Tell the DHCP server we do not accept the offered address.
922 * One reason to decline the lease is when we find out the address
923 * is already in use by another host (through ARP).
924 *
925 * @param netif the netif under DHCP control
926 */
927 static err_t
dhcp_decline(struct netif * netif)928 dhcp_decline(struct netif *netif)
929 {
930 struct dhcp *dhcp = netif_dhcp_data(netif);
931 err_t result = ERR_OK;
932 u16_t msecs;
933 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_decline()\n"));
934 dhcp_set_state(dhcp, DHCP_STATE_BACKING_OFF);
935 /* create and initialize the DHCP message header */
936 result = dhcp_create_msg(netif, dhcp, DHCP_DECLINE);
937 if (result == ERR_OK) {
938 dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
939 dhcp_option_long(dhcp, lwip_ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr)));
940
941 dhcp_option_trailer(dhcp);
942 /* resize pbuf to reflect true size of options */
943 pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
944
945 /* per section 4.4.4, broadcast DECLINE messages */
946 udp_sendto_if_src(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif, IP4_ADDR_ANY);
947 dhcp_delete_msg(dhcp);
948 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_decline: BACKING OFF\n"));
949 } else {
950 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
951 ("dhcp_decline: could not allocate DHCP request\n"));
952 }
953 if (dhcp->tries < 255) {
954 dhcp->tries++;
955 }
956 msecs = 10*1000;
957 dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
958 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_decline(): set request timeout %"U16_F" msecs\n", msecs));
959 return result;
960 }
961 #endif /* DHCP_DOES_ARP_CHECK */
962
963
964 /**
965 * Start the DHCP process, discover a DHCP server.
966 *
967 * @param netif the netif under DHCP control
968 */
969 static err_t
dhcp_discover(struct netif * netif)970 dhcp_discover(struct netif *netif)
971 {
972 struct dhcp *dhcp = netif_dhcp_data(netif);
973 err_t result = ERR_OK;
974 u16_t msecs;
975 u8_t i;
976 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover()\n"));
977 ip4_addr_set_any(&dhcp->offered_ip_addr);
978 dhcp_set_state(dhcp, DHCP_STATE_SELECTING);
979 /* create and initialize the DHCP message header */
980 result = dhcp_create_msg(netif, dhcp, DHCP_DISCOVER);
981 if (result == ERR_OK) {
982 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: making request\n"));
983
984 dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
985 dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif));
986
987 dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, LWIP_ARRAYSIZE(dhcp_discover_request_options));
988 for (i = 0; i < LWIP_ARRAYSIZE(dhcp_discover_request_options); i++) {
989 dhcp_option_byte(dhcp, dhcp_discover_request_options[i]);
990 }
991 dhcp_option_trailer(dhcp);
992
993 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: realloc()ing\n"));
994 pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
995
996 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, DHCP_SERVER_PORT)\n"));
997 udp_sendto_if_src(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif, IP4_ADDR_ANY);
998 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: deleting()ing\n"));
999 dhcp_delete_msg(dhcp);
1000 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover: SELECTING\n"));
1001 } else {
1002 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_discover: could not allocate DHCP request\n"));
1003 }
1004 if (dhcp->tries < 255) {
1005 dhcp->tries++;
1006 }
1007 #if LWIP_DHCP_AUTOIP_COOP
1008 if (dhcp->tries >= LWIP_DHCP_AUTOIP_COOP_TRIES && dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_OFF) {
1009 dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_ON;
1010 autoip_start(netif);
1011 }
1012 #endif /* LWIP_DHCP_AUTOIP_COOP */
1013 msecs = (dhcp->tries < 6 ? 1 << dhcp->tries : 60) * 1000;
1014 dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
1015 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover(): set request timeout %"U16_F" msecs\n", msecs));
1016 return result;
1017 }
1018
1019
1020 /**
1021 * Bind the interface to the offered IP address.
1022 *
1023 * @param netif network interface to bind to the offered address
1024 */
1025 static void
dhcp_bind(struct netif * netif)1026 dhcp_bind(struct netif *netif)
1027 {
1028 u32_t timeout;
1029 struct dhcp *dhcp;
1030 ip4_addr_t sn_mask, gw_addr;
1031 LWIP_ERROR("dhcp_bind: netif != NULL", (netif != NULL), return;);
1032 dhcp = netif_dhcp_data(netif);
1033 LWIP_ERROR("dhcp_bind: dhcp != NULL", (dhcp != NULL), return;);
1034 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));
1035
1036 /* reset time used of lease */
1037 dhcp->lease_used = 0;
1038
1039 if (dhcp->offered_t0_lease != 0xffffffffUL) {
1040 /* set renewal period timer */
1041 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t0 renewal timer %"U32_F" secs\n", dhcp->offered_t0_lease));
1042 timeout = (dhcp->offered_t0_lease + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS;
1043 if (timeout > 0xffff) {
1044 timeout = 0xffff;
1045 }
1046 dhcp->t0_timeout = (u16_t)timeout;
1047 if (dhcp->t0_timeout == 0) {
1048 dhcp->t0_timeout = 1;
1049 }
1050 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t0_lease*1000));
1051 }
1052
1053 /* temporary DHCP lease? */
1054 if (dhcp->offered_t1_renew != 0xffffffffUL) {
1055 /* set renewal period timer */
1056 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t1 renewal timer %"U32_F" secs\n", dhcp->offered_t1_renew));
1057 timeout = (dhcp->offered_t1_renew + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS;
1058 if (timeout > 0xffff) {
1059 timeout = 0xffff;
1060 }
1061 dhcp->t1_timeout = (u16_t)timeout;
1062 if (dhcp->t1_timeout == 0) {
1063 dhcp->t1_timeout = 1;
1064 }
1065 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t1_renew*1000));
1066 dhcp->t1_renew_time = dhcp->t1_timeout;
1067 }
1068 /* set renewal period timer */
1069 if (dhcp->offered_t2_rebind != 0xffffffffUL) {
1070 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t2 rebind timer %"U32_F" secs\n", dhcp->offered_t2_rebind));
1071 timeout = (dhcp->offered_t2_rebind + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS;
1072 if (timeout > 0xffff) {
1073 timeout = 0xffff;
1074 }
1075 dhcp->t2_timeout = (u16_t)timeout;
1076 if (dhcp->t2_timeout == 0) {
1077 dhcp->t2_timeout = 1;
1078 }
1079 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t2_rebind*1000));
1080 dhcp->t2_rebind_time = dhcp->t2_timeout;
1081 }
1082
1083 /* If we have sub 1 minute lease, t2 and t1 will kick in at the same time. */
1084 if ((dhcp->t1_timeout >= dhcp->t2_timeout) && (dhcp->t2_timeout > 0)) {
1085 dhcp->t1_timeout = 0;
1086 }
1087
1088 if (dhcp->subnet_mask_given) {
1089 /* copy offered network mask */
1090 ip4_addr_copy(sn_mask, dhcp->offered_sn_mask);
1091 } else {
1092 /* subnet mask not given, choose a safe subnet mask given the network class */
1093 u8_t first_octet = ip4_addr1(&dhcp->offered_ip_addr);
1094 if (first_octet <= 127) {
1095 ip4_addr_set_u32(&sn_mask, PP_HTONL(0xff000000UL));
1096 } else if (first_octet >= 192) {
1097 ip4_addr_set_u32(&sn_mask, PP_HTONL(0xffffff00UL));
1098 } else {
1099 ip4_addr_set_u32(&sn_mask, PP_HTONL(0xffff0000UL));
1100 }
1101 }
1102
1103 ip4_addr_copy(gw_addr, dhcp->offered_gw_addr);
1104 /* gateway address not given? */
1105 if (ip4_addr_isany_val(gw_addr)) {
1106 /* copy network address */
1107 ip4_addr_get_network(&gw_addr, &dhcp->offered_ip_addr, &sn_mask);
1108 /* use first host address on network as gateway */
1109 ip4_addr_set_u32(&gw_addr, ip4_addr_get_u32(&gw_addr) | PP_HTONL(0x00000001UL));
1110 }
1111
1112 #if LWIP_DHCP_AUTOIP_COOP
1113 if (dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) {
1114 autoip_stop(netif);
1115 dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF;
1116 }
1117 #endif /* LWIP_DHCP_AUTOIP_COOP */
1118
1119 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): IP: 0x%08"X32_F" SN: 0x%08"X32_F" GW: 0x%08"X32_F"\n",
1120 ip4_addr_get_u32(&dhcp->offered_ip_addr), ip4_addr_get_u32(&sn_mask), ip4_addr_get_u32(&gw_addr)));
1121 /* netif is now bound to DHCP leased address - set this before assigning the address
1122 to ensure the callback can use dhcp_supplied_address() */
1123 dhcp_set_state(dhcp, DHCP_STATE_BOUND);
1124
1125 #if DHCP_TIMEOUT_WORKAROUND_FOR_BK_WIFI
1126 dhcp_stop_timeout_check();
1127 #endif
1128
1129 netif_set_addr(netif, &dhcp->offered_ip_addr, &sn_mask, &gw_addr);
1130 /* interface is used by routing now that an address is set */
1131 }
1132
1133 /**
1134 * @ingroup dhcp4
1135 * Renew an existing DHCP lease at the involved DHCP server.
1136 *
1137 * @param netif network interface which must renew its lease
1138 */
1139 err_t
dhcp_renew(struct netif * netif)1140 dhcp_renew(struct netif *netif)
1141 {
1142 struct dhcp *dhcp = netif_dhcp_data(netif);
1143 err_t result;
1144 u16_t msecs;
1145 u8_t i;
1146 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_renew()\n"));
1147 dhcp_set_state(dhcp, DHCP_STATE_RENEWING);
1148
1149 /* create and initialize the DHCP message header */
1150 result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST);
1151 if (result == ERR_OK) {
1152 dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
1153 dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif));
1154
1155 dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, LWIP_ARRAYSIZE(dhcp_discover_request_options));
1156 for (i = 0; i < LWIP_ARRAYSIZE(dhcp_discover_request_options); i++) {
1157 dhcp_option_byte(dhcp, dhcp_discover_request_options[i]);
1158 }
1159
1160 #if LWIP_NETIF_HOSTNAME
1161 dhcp_option_hostname(dhcp, netif);
1162 #endif /* LWIP_NETIF_HOSTNAME */
1163
1164 /* append DHCP message trailer */
1165 dhcp_option_trailer(dhcp);
1166
1167 pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
1168
1169 udp_sendto_if(dhcp_pcb, dhcp->p_out, &dhcp->server_ip_addr, DHCP_SERVER_PORT, netif);
1170 dhcp_delete_msg(dhcp);
1171
1172 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_renew: RENEWING\n"));
1173 } else {
1174 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_renew: could not allocate DHCP request\n"));
1175 }
1176 if (dhcp->tries < 255) {
1177 dhcp->tries++;
1178 }
1179 /* back-off on retries, but to a maximum of 20 seconds */
1180 msecs = dhcp->tries < 10 ? dhcp->tries * 2000 : 20 * 1000;
1181 dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
1182 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_renew(): set request timeout %"U16_F" msecs\n", msecs));
1183 return result;
1184 }
1185
1186 /**
1187 * Rebind with a DHCP server for an existing DHCP lease.
1188 *
1189 * @param netif network interface which must rebind with a DHCP server
1190 */
1191 static err_t
dhcp_rebind(struct netif * netif)1192 dhcp_rebind(struct netif *netif)
1193 {
1194 struct dhcp *dhcp = netif_dhcp_data(netif);
1195 err_t result;
1196 u16_t msecs;
1197 u8_t i;
1198 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind()\n"));
1199 dhcp_set_state(dhcp, DHCP_STATE_REBINDING);
1200
1201 /* create and initialize the DHCP message header */
1202 result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST);
1203 if (result == ERR_OK) {
1204 dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
1205 dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif));
1206
1207 dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, LWIP_ARRAYSIZE(dhcp_discover_request_options));
1208 for (i = 0; i < LWIP_ARRAYSIZE(dhcp_discover_request_options); i++) {
1209 dhcp_option_byte(dhcp, dhcp_discover_request_options[i]);
1210 }
1211
1212 #if LWIP_NETIF_HOSTNAME
1213 dhcp_option_hostname(dhcp, netif);
1214 #endif /* LWIP_NETIF_HOSTNAME */
1215
1216 dhcp_option_trailer(dhcp);
1217
1218 pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
1219
1220 /* broadcast to server */
1221 udp_sendto_if(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
1222 dhcp_delete_msg(dhcp);
1223 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind: REBINDING\n"));
1224 } else {
1225 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_rebind: could not allocate DHCP request\n"));
1226 }
1227 if (dhcp->tries < 255) {
1228 dhcp->tries++;
1229 }
1230 msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000;
1231 dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
1232 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind(): set request timeout %"U16_F" msecs\n", msecs));
1233 return result;
1234 }
1235
1236 /**
1237 * Enter REBOOTING state to verify an existing lease
1238 *
1239 * @param netif network interface which must reboot
1240 */
1241 static err_t
dhcp_reboot(struct netif * netif)1242 dhcp_reboot(struct netif *netif)
1243 {
1244 struct dhcp *dhcp = netif_dhcp_data(netif);
1245 err_t result;
1246 u16_t msecs;
1247 u8_t i;
1248 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot()\n"));
1249 dhcp_set_state(dhcp, DHCP_STATE_REBOOTING);
1250
1251 /* create and initialize the DHCP message header */
1252 result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST);
1253 if (result == ERR_OK) {
1254 dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
1255 dhcp_option_short(dhcp, 576);
1256
1257 dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
1258 dhcp_option_long(dhcp, lwip_ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr)));
1259
1260 dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, LWIP_ARRAYSIZE(dhcp_discover_request_options));
1261 for (i = 0; i < LWIP_ARRAYSIZE(dhcp_discover_request_options); i++) {
1262 dhcp_option_byte(dhcp, dhcp_discover_request_options[i]);
1263 }
1264
1265 dhcp_option_trailer(dhcp);
1266
1267 pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
1268
1269 /* broadcast to server */
1270 udp_sendto_if(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
1271 dhcp_delete_msg(dhcp);
1272 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot: REBOOTING\n"));
1273 } else {
1274 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_reboot: could not allocate DHCP request\n"));
1275 }
1276 if (dhcp->tries < 255) {
1277 dhcp->tries++;
1278 }
1279 msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000;
1280 dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
1281 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot(): set request timeout %"U16_F" msecs\n", msecs));
1282 return result;
1283 }
1284
1285
1286 /**
1287 * @ingroup dhcp4
1288 * Release a DHCP lease (usually called before @ref dhcp_stop).
1289 *
1290 * @param netif network interface which must release its lease
1291 */
1292 err_t
dhcp_release(struct netif * netif)1293 dhcp_release(struct netif *netif)
1294 {
1295 struct dhcp *dhcp = netif_dhcp_data(netif);
1296 err_t result;
1297 ip_addr_t server_ip_addr;
1298 u8_t is_dhcp_supplied_address;
1299
1300 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_release()\n"));
1301 if (dhcp == NULL) {
1302 return ERR_ARG;
1303 }
1304 ip_addr_copy(server_ip_addr, dhcp->server_ip_addr);
1305
1306 is_dhcp_supplied_address = dhcp_supplied_address(netif);
1307
1308 /* idle DHCP client */
1309 dhcp_set_state(dhcp, DHCP_STATE_OFF);
1310 /* clean old DHCP offer */
1311 ip_addr_set_zero_ip4(&dhcp->server_ip_addr);
1312 ip4_addr_set_zero(&dhcp->offered_ip_addr);
1313 ip4_addr_set_zero(&dhcp->offered_sn_mask);
1314 ip4_addr_set_zero(&dhcp->offered_gw_addr);
1315 #if LWIP_DHCP_BOOTP_FILE
1316 ip4_addr_set_zero(&dhcp->offered_si_addr);
1317 #endif /* LWIP_DHCP_BOOTP_FILE */
1318 dhcp->offered_t0_lease = dhcp->offered_t1_renew = dhcp->offered_t2_rebind = 0;
1319 dhcp->t1_renew_time = dhcp->t2_rebind_time = dhcp->lease_used = dhcp->t0_timeout = 0;
1320
1321 if (!is_dhcp_supplied_address) {
1322 /* don't issue release message when address is not dhcp-assigned */
1323 return ERR_OK;
1324 }
1325
1326 /* create and initialize the DHCP message header */
1327 result = dhcp_create_msg(netif, dhcp, DHCP_RELEASE);
1328 if (result == ERR_OK) {
1329 dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4);
1330 dhcp_option_long(dhcp, lwip_ntohl(ip4_addr_get_u32(ip_2_ip4(&server_ip_addr))));
1331
1332 dhcp_option_trailer(dhcp);
1333
1334 pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
1335
1336 udp_sendto_if(dhcp_pcb, dhcp->p_out, &server_ip_addr, DHCP_SERVER_PORT, netif);
1337 dhcp_delete_msg(dhcp);
1338 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_release: RELEASED, DHCP_STATE_OFF\n"));
1339 } else {
1340 /* sending release failed, but that's not a problem since the correct behaviour of dhcp does not rely on release */
1341 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_release: could not allocate DHCP request\n"));
1342 }
1343 /* remove IP address from interface (prevents routing from selecting this interface) */
1344 netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4);
1345
1346 return result;
1347 }
1348
1349 /**
1350 * @ingroup dhcp4
1351 * Remove the DHCP client from the interface.
1352 *
1353 * @param netif The network interface to stop DHCP on
1354 */
1355 void
dhcp_stop(struct netif * netif)1356 dhcp_stop(struct netif *netif)
1357 {
1358 struct dhcp *dhcp;
1359 LWIP_ERROR("dhcp_stop: netif != NULL", (netif != NULL), return;);
1360 dhcp = netif_dhcp_data(netif);
1361
1362 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_stop()\n"));
1363 /* netif is DHCP configured? */
1364 if (dhcp != NULL) {
1365 #if LWIP_DHCP_AUTOIP_COOP
1366 if (dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) {
1367 autoip_stop(netif);
1368 dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF;
1369 }
1370 #endif /* LWIP_DHCP_AUTOIP_COOP */
1371
1372 LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL);
1373 dhcp_set_state(dhcp, DHCP_STATE_OFF);
1374
1375 if (dhcp->pcb_allocated != 0) {
1376 dhcp_dec_pcb_refcount(); /* free DHCP PCB if not needed any more */
1377 dhcp->pcb_allocated = 0;
1378 }
1379 }
1380 }
1381
1382 /*
1383 * Set the DHCP state of a DHCP client.
1384 *
1385 * If the state changed, reset the number of tries.
1386 */
1387 static void
dhcp_set_state(struct dhcp * dhcp,u8_t new_state)1388 dhcp_set_state(struct dhcp *dhcp, u8_t new_state)
1389 {
1390 if (new_state != dhcp->state) {
1391 dhcp->state = new_state;
1392 dhcp->tries = 0;
1393 dhcp->request_timeout = 0;
1394 }
1395 }
1396
1397 /*
1398 * Concatenate an option type and length field to the outgoing
1399 * DHCP message.
1400 *
1401 */
1402 static void
dhcp_option(struct dhcp * dhcp,u8_t option_type,u8_t option_len)1403 dhcp_option(struct dhcp *dhcp, u8_t option_type, u8_t option_len)
1404 {
1405 LWIP_ASSERT("dhcp_option: dhcp->options_out_len + 2 + option_len <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 2U + option_len <= DHCP_OPTIONS_LEN);
1406 dhcp->msg_out->options[dhcp->options_out_len++] = option_type;
1407 dhcp->msg_out->options[dhcp->options_out_len++] = option_len;
1408 }
1409 /*
1410 * Concatenate a single byte to the outgoing DHCP message.
1411 *
1412 */
1413 static void
dhcp_option_byte(struct dhcp * dhcp,u8_t value)1414 dhcp_option_byte(struct dhcp *dhcp, u8_t value)
1415 {
1416 LWIP_ASSERT("dhcp_option_byte: dhcp->options_out_len < DHCP_OPTIONS_LEN", dhcp->options_out_len < DHCP_OPTIONS_LEN);
1417 dhcp->msg_out->options[dhcp->options_out_len++] = value;
1418 }
1419
1420 static void
dhcp_option_short(struct dhcp * dhcp,u16_t value)1421 dhcp_option_short(struct dhcp *dhcp, u16_t value)
1422 {
1423 LWIP_ASSERT("dhcp_option_short: dhcp->options_out_len + 2 <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 2U <= DHCP_OPTIONS_LEN);
1424 dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0xff00U) >> 8);
1425 dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t) (value & 0x00ffU);
1426 }
1427
1428 static void
dhcp_option_long(struct dhcp * dhcp,u32_t value)1429 dhcp_option_long(struct dhcp *dhcp, u32_t value)
1430 {
1431 LWIP_ASSERT("dhcp_option_long: dhcp->options_out_len + 4 <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 4U <= DHCP_OPTIONS_LEN);
1432 dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0xff000000UL) >> 24);
1433 dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x00ff0000UL) >> 16);
1434 dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x0000ff00UL) >> 8);
1435 dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x000000ffUL));
1436 }
1437
1438 #if LWIP_NETIF_HOSTNAME
1439 static void
dhcp_option_hostname(struct dhcp * dhcp,struct netif * netif)1440 dhcp_option_hostname(struct dhcp *dhcp, struct netif *netif)
1441 {
1442 netif_set_hostname(netif, "Tmall-Genie");
1443 if (netif->hostname != NULL) {
1444 size_t namelen = strlen(netif->hostname);
1445 if (namelen > 0) {
1446 size_t len;
1447 const char *p = netif->hostname;
1448 /* Shrink len to available bytes (need 2 bytes for OPTION_HOSTNAME
1449 and 1 byte for trailer) */
1450 size_t available = DHCP_OPTIONS_LEN - dhcp->options_out_len - 3;
1451 LWIP_ASSERT("DHCP: hostname is too long!", namelen <= available);
1452 len = LWIP_MIN(namelen, available);
1453 LWIP_ASSERT("DHCP: hostname is too long!", len <= 0xFF);
1454 dhcp_option(dhcp, DHCP_OPTION_HOSTNAME, (u8_t)len);
1455 while (len--) {
1456 dhcp_option_byte(dhcp, *p++);
1457 }
1458 }
1459 }
1460 }
1461 #endif /* LWIP_NETIF_HOSTNAME */
1462
1463 /**
1464 * Extract the DHCP message and the DHCP options.
1465 *
1466 * Extract the DHCP message and the DHCP options, each into a contiguous
1467 * piece of memory. As a DHCP message is variable sized by its options,
1468 * and also allows overriding some fields for options, the easy approach
1469 * is to first unfold the options into a contiguous piece of memory, and
1470 * use that further on.
1471 *
1472 */
1473 static err_t
dhcp_parse_reply(struct dhcp * dhcp,struct pbuf * p)1474 dhcp_parse_reply(struct dhcp *dhcp, struct pbuf *p)
1475 {
1476 u8_t *options;
1477 u16_t offset;
1478 u16_t offset_max;
1479 u16_t options_idx;
1480 u16_t options_idx_max;
1481 struct pbuf *q;
1482 int parse_file_as_options = 0;
1483 int parse_sname_as_options = 0;
1484
1485 /* clear received options */
1486 dhcp_clear_all_options(dhcp);
1487 /* check that beginning of dhcp_msg (up to and including chaddr) is in first pbuf */
1488 if (p->len < DHCP_SNAME_OFS) {
1489 return ERR_BUF;
1490 }
1491 dhcp->msg_in = (struct dhcp_msg *)p->payload;
1492 #if LWIP_DHCP_BOOTP_FILE
1493 /* clear boot file name */
1494 dhcp->boot_file_name[0] = 0;
1495 #endif /* LWIP_DHCP_BOOTP_FILE */
1496
1497 /* parse options */
1498
1499 /* start with options field */
1500 options_idx = DHCP_OPTIONS_OFS;
1501 /* parse options to the end of the received packet */
1502 options_idx_max = p->tot_len;
1503 again:
1504 q = p;
1505 while ((q != NULL) && (options_idx >= q->len)) {
1506 options_idx -= q->len;
1507 options_idx_max -= q->len;
1508 q = q->next;
1509 }
1510 if (q == NULL) {
1511 return ERR_BUF;
1512 }
1513 offset = options_idx;
1514 offset_max = options_idx_max;
1515 options = (u8_t*)q->payload;
1516 /* at least 1 byte to read and no end marker, then at least 3 bytes to read? */
1517 while ((q != NULL) && (options[offset] != DHCP_OPTION_END) && (offset < offset_max)) {
1518 u8_t op = options[offset];
1519 u8_t len;
1520 u8_t decode_len = 0;
1521 int decode_idx = -1;
1522 u16_t val_offset = offset + 2;
1523 /* len byte might be in the next pbuf */
1524 if ((offset + 1) < q->len) {
1525 len = options[offset + 1];
1526 } else {
1527 len = (q->next != NULL ? ((u8_t*)q->next->payload)[0] : 0);
1528 }
1529 /* LWIP_DEBUGF(DHCP_DEBUG, ("msg_offset=%"U16_F", q->len=%"U16_F, msg_offset, q->len)); */
1530 decode_len = len;
1531 switch(op) {
1532 /* case(DHCP_OPTION_END): handled above */
1533 case(DHCP_OPTION_PAD):
1534 /* special option: no len encoded */
1535 decode_len = len = 0;
1536 /* will be increased below */
1537 offset--;
1538 break;
1539 case(DHCP_OPTION_SUBNET_MASK):
1540 LWIP_ERROR("len == 4", len == 4, return ERR_VAL;);
1541 decode_idx = DHCP_OPTION_IDX_SUBNET_MASK;
1542 break;
1543 case(DHCP_OPTION_ROUTER):
1544 decode_len = 4; /* only copy the first given router */
1545 LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;);
1546 decode_idx = DHCP_OPTION_IDX_ROUTER;
1547 break;
1548 case(DHCP_OPTION_DNS_SERVER):
1549 /* special case: there might be more than one server */
1550 LWIP_ERROR("len %% 4 == 0", len % 4 == 0, return ERR_VAL;);
1551 /* limit number of DNS servers */
1552 decode_len = LWIP_MIN(len, 4 * DNS_MAX_SERVERS);
1553 LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;);
1554 decode_idx = DHCP_OPTION_IDX_DNS_SERVER;
1555 break;
1556 case(DHCP_OPTION_LEASE_TIME):
1557 LWIP_ERROR("len == 4", len == 4, return ERR_VAL;);
1558 decode_idx = DHCP_OPTION_IDX_LEASE_TIME;
1559 break;
1560 #if LWIP_DHCP_GET_NTP_SRV
1561 case(DHCP_OPTION_NTP):
1562 /* special case: there might be more than one server */
1563 LWIP_ERROR("len %% 4 == 0", len % 4 == 0, return ERR_VAL;);
1564 /* limit number of NTP servers */
1565 decode_len = LWIP_MIN(len, 4 * LWIP_DHCP_MAX_NTP_SERVERS);
1566 LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;);
1567 decode_idx = DHCP_OPTION_IDX_NTP_SERVER;
1568 break;
1569 #endif /* LWIP_DHCP_GET_NTP_SRV*/
1570 case(DHCP_OPTION_OVERLOAD):
1571 LWIP_ERROR("len == 1", len == 1, return ERR_VAL;);
1572 decode_idx = DHCP_OPTION_IDX_OVERLOAD;
1573 break;
1574 case(DHCP_OPTION_MESSAGE_TYPE):
1575 LWIP_ERROR("len == 1", len == 1, return ERR_VAL;);
1576 decode_idx = DHCP_OPTION_IDX_MSG_TYPE;
1577 break;
1578 case(DHCP_OPTION_SERVER_ID):
1579 LWIP_ERROR("len == 4", len == 4, return ERR_VAL;);
1580 decode_idx = DHCP_OPTION_IDX_SERVER_ID;
1581 break;
1582 case(DHCP_OPTION_T1):
1583 LWIP_ERROR("len == 4", len == 4, return ERR_VAL;);
1584 decode_idx = DHCP_OPTION_IDX_T1;
1585 break;
1586 case(DHCP_OPTION_T2):
1587 LWIP_ERROR("len == 4", len == 4, return ERR_VAL;);
1588 decode_idx = DHCP_OPTION_IDX_T2;
1589 break;
1590 default:
1591 decode_len = 0;
1592 LWIP_DEBUGF(DHCP_DEBUG, ("skipping option %"U16_F" in options\n", (u16_t)op));
1593 break;
1594 }
1595 offset += len + 2;
1596 if (decode_len > 0) {
1597 u32_t value = 0;
1598 u16_t copy_len;
1599 decode_next:
1600 LWIP_ASSERT("check decode_idx", decode_idx >= 0 && decode_idx < DHCP_OPTION_IDX_MAX);
1601 if (!dhcp_option_given(dhcp, decode_idx)) {
1602 copy_len = LWIP_MIN(decode_len, 4);
1603 if (pbuf_copy_partial(q, &value, copy_len, val_offset) != copy_len) {
1604 return ERR_BUF;
1605 }
1606 if (decode_len > 4) {
1607 /* decode more than one u32_t */
1608 LWIP_ERROR("decode_len %% 4 == 0", decode_len % 4 == 0, return ERR_VAL;);
1609 dhcp_got_option(dhcp, decode_idx);
1610 dhcp_set_option_value(dhcp, decode_idx, lwip_htonl(value));
1611 decode_len -= 4;
1612 val_offset += 4;
1613 decode_idx++;
1614 goto decode_next;
1615 } else if (decode_len == 4) {
1616 value = lwip_ntohl(value);
1617 } else {
1618 u8_t temp;
1619 LWIP_ERROR("invalid decode_len", decode_len == 1, return ERR_VAL;);
1620 temp = ((u8_t*)&value)[0];
1621 value = (u32_t) temp;
1622 }
1623 dhcp_got_option(dhcp, decode_idx);
1624 dhcp_set_option_value(dhcp, decode_idx, value);
1625 }
1626 }
1627 if (offset >= q->len) {
1628 offset -= q->len;
1629 offset_max -= q->len;
1630 if ((offset < offset_max) && offset_max) {
1631 q = q->next;
1632 LWIP_ASSERT("next pbuf was null", q);
1633 if (q != NULL)
1634 options = (u8_t*)q->payload;
1635 } else {
1636 /* We've run out of bytes, probably no end marker. Don't proceed. */
1637 break;
1638 }
1639 }
1640 }
1641 /* is this an overloaded message? */
1642 if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_OVERLOAD)) {
1643 u32_t overload = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_OVERLOAD);
1644 dhcp_clear_option(dhcp, DHCP_OPTION_IDX_OVERLOAD);
1645 if (overload == DHCP_OVERLOAD_FILE) {
1646 parse_file_as_options = 1;
1647 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded file field\n"));
1648 } else if (overload == DHCP_OVERLOAD_SNAME) {
1649 parse_sname_as_options = 1;
1650 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded sname field\n"));
1651 } else if (overload == DHCP_OVERLOAD_SNAME_FILE) {
1652 parse_sname_as_options = 1;
1653 parse_file_as_options = 1;
1654 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded sname and file field\n"));
1655 } else {
1656 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("invalid overload option: %d\n", (int)overload));
1657 }
1658 #if LWIP_DHCP_BOOTP_FILE
1659 if (!parse_file_as_options) {
1660 /* only do this for ACK messages */
1661 if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_MSG_TYPE) &&
1662 (dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_MSG_TYPE) == DHCP_ACK))
1663 /* copy bootp file name, don't care for sname (server hostname) */
1664 if (pbuf_copy_partial(p, dhcp->boot_file_name, DHCP_FILE_LEN-1, DHCP_FILE_OFS) != (DHCP_FILE_LEN-1)) {
1665 return ERR_BUF;
1666 }
1667 /* make sure the string is really NULL-terminated */
1668 dhcp->boot_file_name[DHCP_FILE_LEN-1] = 0;
1669 }
1670 #endif /* LWIP_DHCP_BOOTP_FILE */
1671 }
1672 if (parse_file_as_options) {
1673 /* if both are overloaded, parse file first and then sname (RFC 2131 ch. 4.1) */
1674 parse_file_as_options = 0;
1675 options_idx = DHCP_FILE_OFS;
1676 options_idx_max = DHCP_FILE_OFS + DHCP_FILE_LEN;
1677 goto again;
1678 } else if (parse_sname_as_options) {
1679 parse_sname_as_options = 0;
1680 options_idx = DHCP_SNAME_OFS;
1681 options_idx_max = DHCP_SNAME_OFS + DHCP_SNAME_LEN;
1682 goto again;
1683 }
1684 return ERR_OK;
1685 }
1686
1687 /**
1688 * If an incoming DHCP message is in response to us, then trigger the state machine
1689 */
1690 static void
dhcp_recv(void * arg,struct udp_pcb * pcb,struct pbuf * p,const ip_addr_t * addr,u16_t port)1691 dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
1692 {
1693 struct netif *netif = ip_current_input_netif();
1694 struct dhcp *dhcp = netif_dhcp_data(netif);
1695 struct dhcp_msg *reply_msg = (struct dhcp_msg *)p->payload;
1696 u8_t msg_type;
1697 u8_t i;
1698
1699 LWIP_UNUSED_ARG(arg);
1700
1701 /* Caught DHCP message from netif that does not have DHCP enabled? -> not interested */
1702 if ((dhcp == NULL) || (dhcp->pcb_allocated == 0)) {
1703 goto free_pbuf_and_return;
1704 }
1705
1706 LWIP_ASSERT("invalid server address type", IP_IS_V4(addr));
1707
1708 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,
1709 ip4_addr1_16(ip_2_ip4(addr)), ip4_addr2_16(ip_2_ip4(addr)), ip4_addr3_16(ip_2_ip4(addr)), ip4_addr4_16(ip_2_ip4(addr)), port));
1710 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("pbuf->len = %"U16_F"\n", p->len));
1711 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("pbuf->tot_len = %"U16_F"\n", p->tot_len));
1712 /* prevent warnings about unused arguments */
1713 LWIP_UNUSED_ARG(pcb);
1714 LWIP_UNUSED_ARG(addr);
1715 LWIP_UNUSED_ARG(port);
1716
1717 LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL);
1718
1719 if (p->len < DHCP_MIN_REPLY_LEN) {
1720 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("DHCP reply message or pbuf too short\n"));
1721 goto free_pbuf_and_return;
1722 }
1723
1724 if (reply_msg->op != DHCP_BOOTREPLY) {
1725 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));
1726 goto free_pbuf_and_return;
1727 }
1728 /* iterate through hardware address and match against DHCP message */
1729 for (i = 0; i < netif->hwaddr_len && i < NETIF_MAX_HWADDR_LEN && i < DHCP_CHADDR_LEN; i++) {
1730 if (netif->hwaddr[i] != reply_msg->chaddr[i]) {
1731 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
1732 ("netif->hwaddr[%"U16_F"]==%02"X16_F" != reply_msg->chaddr[%"U16_F"]==%02"X16_F"\n",
1733 (u16_t)i, (u16_t)netif->hwaddr[i], (u16_t)i, (u16_t)reply_msg->chaddr[i]));
1734 goto free_pbuf_and_return;
1735 }
1736 }
1737 /* match transaction ID against what we expected */
1738 if (lwip_ntohl(reply_msg->xid) != dhcp->xid) {
1739 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
1740 ("transaction id mismatch reply_msg->xid(%"X32_F")!=dhcp->xid(%"X32_F")\n",lwip_ntohl(reply_msg->xid),dhcp->xid));
1741 goto free_pbuf_and_return;
1742 }
1743 /* option fields could be unfold? */
1744 if (dhcp_parse_reply(dhcp, p) != ERR_OK) {
1745 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
1746 ("problem unfolding DHCP message - too short on memory?\n"));
1747 goto free_pbuf_and_return;
1748 }
1749
1750 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("searching DHCP_OPTION_MESSAGE_TYPE\n"));
1751 /* obtain pointer to DHCP message type */
1752 if (!dhcp_option_given(dhcp, DHCP_OPTION_IDX_MSG_TYPE)) {
1753 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("DHCP_OPTION_MESSAGE_TYPE option not found\n"));
1754 goto free_pbuf_and_return;
1755 }
1756
1757 /* read DHCP message type */
1758 msg_type = (u8_t)dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_MSG_TYPE);
1759 /* message type is DHCP ACK? */
1760 if (msg_type == DHCP_ACK) {
1761 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_ACK received\n"));
1762 /* in requesting state? */
1763 if (dhcp->state == DHCP_STATE_REQUESTING) {
1764 dhcp_handle_ack(netif);
1765 #if DHCP_DOES_ARP_CHECK
1766 if ((netif->flags & NETIF_FLAG_ETHARP) != 0) {
1767 /* check if the acknowledged lease address is already in use */
1768 dhcp_check(netif);
1769 } else {
1770 /* bind interface to the acknowledged lease address */
1771 dhcp_bind(netif);
1772 }
1773 #else
1774 /* bind interface to the acknowledged lease address */
1775 dhcp_bind(netif);
1776 #endif
1777 }
1778 /* already bound to the given lease address? */
1779 else if ((dhcp->state == DHCP_STATE_REBOOTING) || (dhcp->state == DHCP_STATE_REBINDING) ||
1780 (dhcp->state == DHCP_STATE_RENEWING)) {
1781 dhcp_handle_ack(netif);
1782 dhcp_bind(netif);
1783 }
1784 }
1785 /* received a DHCP_NAK in appropriate state? */
1786 else if ((msg_type == DHCP_NAK) &&
1787 ((dhcp->state == DHCP_STATE_REBOOTING) || (dhcp->state == DHCP_STATE_REQUESTING) ||
1788 (dhcp->state == DHCP_STATE_REBINDING) || (dhcp->state == DHCP_STATE_RENEWING ))) {
1789 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_NAK received\n"));
1790 dhcp_handle_nak(netif);
1791 }
1792 /* received a DHCP_OFFER in DHCP_STATE_SELECTING state? */
1793 else if ((msg_type == DHCP_OFFER) && (dhcp->state == DHCP_STATE_SELECTING)) {
1794 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_OFFER received in DHCP_STATE_SELECTING state\n"));
1795 dhcp->request_timeout = 0;
1796 /* remember offered lease */
1797 dhcp_handle_offer(netif);
1798 }
1799
1800 free_pbuf_and_return:
1801 if (dhcp != NULL) {
1802 dhcp->msg_in = NULL;
1803 }
1804 pbuf_free(p);
1805 }
1806
1807 /**
1808 * Create a DHCP request, fill in common headers
1809 *
1810 * @param netif the netif under DHCP control
1811 * @param dhcp dhcp control struct
1812 * @param message_type message type of the request
1813 */
1814 static err_t
dhcp_create_msg(struct netif * netif,struct dhcp * dhcp,u8_t message_type)1815 dhcp_create_msg(struct netif *netif, struct dhcp *dhcp, u8_t message_type)
1816 {
1817 u16_t i;
1818 #ifndef DHCP_GLOBAL_XID
1819 /** default global transaction identifier starting value (easy to match
1820 * with a packet analyser). We simply increment for each new request.
1821 * Predefine DHCP_GLOBAL_XID to a better value or a function call to generate one
1822 * at runtime, any supporting function prototypes can be defined in DHCP_GLOBAL_XID_HEADER */
1823 #if DHCP_CREATE_RAND_XID && defined(LWIP_RAND)
1824 static u32_t xid;
1825 #else /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */
1826 static u32_t xid = 0xABCD0000;
1827 #endif /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */
1828 #else
1829 if (!xid_initialised) {
1830 xid = DHCP_GLOBAL_XID;
1831 xid_initialised = !xid_initialised;
1832 }
1833 #endif
1834 LWIP_ERROR("dhcp_create_msg: netif != NULL", (netif != NULL), return ERR_ARG;);
1835 LWIP_ERROR("dhcp_create_msg: dhcp != NULL", (dhcp != NULL), return ERR_VAL;);
1836 LWIP_ASSERT("dhcp_create_msg: dhcp->p_out == NULL", dhcp->p_out == NULL);
1837 LWIP_ASSERT("dhcp_create_msg: dhcp->msg_out == NULL", dhcp->msg_out == NULL);
1838 dhcp->p_out = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcp_msg), PBUF_RAM);
1839 if (dhcp->p_out == NULL) {
1840 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
1841 ("dhcp_create_msg(): could not allocate pbuf\n"));
1842 return ERR_MEM;
1843 }
1844 LWIP_ASSERT("dhcp_create_msg: check that first pbuf can hold struct dhcp_msg",
1845 (dhcp->p_out->len >= sizeof(struct dhcp_msg)));
1846
1847 /* DHCP_REQUEST should reuse 'xid' from DHCPOFFER */
1848 if (message_type != DHCP_REQUEST) {
1849 /* reuse transaction identifier in retransmissions */
1850 if (dhcp->tries == 0) {
1851 #if DHCP_CREATE_RAND_XID && defined(LWIP_RAND)
1852 xid = LWIP_RAND();
1853 #else /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */
1854 xid++;
1855 #endif /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */
1856 }
1857 dhcp->xid = xid;
1858 }
1859 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
1860 ("transaction id xid(%"X32_F")\n", xid));
1861
1862 dhcp->msg_out = (struct dhcp_msg *)dhcp->p_out->payload;
1863
1864 dhcp->msg_out->op = DHCP_BOOTREQUEST;
1865 /* @todo: make link layer independent */
1866 dhcp->msg_out->htype = DHCP_HTYPE_ETH;
1867 dhcp->msg_out->hlen = netif->hwaddr_len;
1868 dhcp->msg_out->hops = 0;
1869 dhcp->msg_out->xid = lwip_htonl(dhcp->xid);
1870 dhcp->msg_out->secs = 0;
1871 /* we don't need the broadcast flag since we can receive unicast traffic
1872 before being fully configured! */
1873 dhcp->msg_out->flags = 0;
1874 ip4_addr_set_zero(&dhcp->msg_out->ciaddr);
1875 /* set ciaddr to netif->ip_addr based on message_type and state */
1876 if ((message_type == DHCP_INFORM) || (message_type == DHCP_DECLINE) || (message_type == DHCP_RELEASE) ||
1877 ((message_type == DHCP_REQUEST) && /* DHCP_STATE_BOUND not used for sending! */
1878 ((dhcp->state== DHCP_STATE_RENEWING) || dhcp->state== DHCP_STATE_REBINDING))) {
1879 ip4_addr_copy(dhcp->msg_out->ciaddr, *netif_ip4_addr(netif));
1880 }
1881 ip4_addr_set_zero(&dhcp->msg_out->yiaddr);
1882 ip4_addr_set_zero(&dhcp->msg_out->siaddr);
1883 ip4_addr_set_zero(&dhcp->msg_out->giaddr);
1884 for (i = 0; i < DHCP_CHADDR_LEN; i++) {
1885 /* copy netif hardware address, pad with zeroes */
1886 dhcp->msg_out->chaddr[i] = (i < netif->hwaddr_len && i < NETIF_MAX_HWADDR_LEN) ? netif->hwaddr[i] : 0/* pad byte*/;
1887 }
1888 for (i = 0; i < DHCP_SNAME_LEN; i++) {
1889 dhcp->msg_out->sname[i] = 0;
1890 }
1891 for (i = 0; i < DHCP_FILE_LEN; i++) {
1892 dhcp->msg_out->file[i] = 0;
1893 }
1894 dhcp->msg_out->cookie = PP_HTONL(DHCP_MAGIC_COOKIE);
1895 dhcp->options_out_len = 0;
1896 /* fill options field with an incrementing array (for debugging purposes) */
1897 for (i = 0; i < DHCP_OPTIONS_LEN; i++) {
1898 dhcp->msg_out->options[i] = (u8_t)i; /* for debugging only, no matter if truncated */
1899 }
1900 /* Add option MESSAGE_TYPE */
1901 dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
1902 dhcp_option_byte(dhcp, message_type);
1903 return ERR_OK;
1904 }
1905
1906 /**
1907 * Free previously allocated memory used to send a DHCP request.
1908 *
1909 * @param dhcp the dhcp struct to free the request from
1910 */
1911 static void
dhcp_delete_msg(struct dhcp * dhcp)1912 dhcp_delete_msg(struct dhcp *dhcp)
1913 {
1914 LWIP_ERROR("dhcp_delete_msg: dhcp != NULL", (dhcp != NULL), return;);
1915 LWIP_ASSERT("dhcp_delete_msg: dhcp->p_out != NULL", dhcp->p_out != NULL);
1916 LWIP_ASSERT("dhcp_delete_msg: dhcp->msg_out != NULL", dhcp->msg_out != NULL);
1917 if (dhcp->p_out != NULL) {
1918 pbuf_free(dhcp->p_out);
1919 }
1920 dhcp->p_out = NULL;
1921 dhcp->msg_out = NULL;
1922 }
1923
1924 /**
1925 * Add a DHCP message trailer
1926 *
1927 * Adds the END option to the DHCP message, and if
1928 * necessary, up to three padding bytes.
1929 *
1930 * @param dhcp DHCP state structure
1931 */
1932 static void
dhcp_option_trailer(struct dhcp * dhcp)1933 dhcp_option_trailer(struct dhcp *dhcp)
1934 {
1935 LWIP_ERROR("dhcp_option_trailer: dhcp != NULL", (dhcp != NULL), return;);
1936 LWIP_ASSERT("dhcp_option_trailer: dhcp->msg_out != NULL\n", dhcp->msg_out != NULL);
1937 LWIP_ASSERT("dhcp_option_trailer: dhcp->options_out_len < DHCP_OPTIONS_LEN\n", dhcp->options_out_len < DHCP_OPTIONS_LEN);
1938 dhcp->msg_out->options[dhcp->options_out_len++] = DHCP_OPTION_END;
1939 /* packet is too small, or not 4 byte aligned? */
1940 while (((dhcp->options_out_len < DHCP_MIN_OPTIONS_LEN) || (dhcp->options_out_len & 3)) &&
1941 (dhcp->options_out_len < DHCP_OPTIONS_LEN)) {
1942 /* add a fill/padding byte */
1943 dhcp->msg_out->options[dhcp->options_out_len++] = 0;
1944 }
1945 }
1946
1947 /** check if DHCP supplied netif->ip_addr
1948 *
1949 * @param netif the netif to check
1950 * @return 1 if DHCP supplied netif->ip_addr (states BOUND or RENEWING),
1951 * 0 otherwise
1952 */
1953 u8_t
dhcp_supplied_address(const struct netif * netif)1954 dhcp_supplied_address(const struct netif *netif)
1955 {
1956 if ((netif != NULL) && (netif_dhcp_data(netif) != NULL)) {
1957 struct dhcp* dhcp = netif_dhcp_data(netif);
1958 return (dhcp->state == DHCP_STATE_BOUND) || (dhcp->state == DHCP_STATE_RENEWING);
1959 }
1960 return 0;
1961 }
1962
1963 #if DHCP_TIMEOUT_WORKAROUND_FOR_BK_WIFI
dhcp_check_status(void)1964 void dhcp_check_status(void)
1965 {
1966 struct netif *netif = netif_list;
1967
1968 while (netif != NULL) {
1969 struct dhcp *dhcp = netif_dhcp_data(netif);
1970
1971 if(dhcp != NULL){
1972 if(dhcp->state != DHCP_STATE_BOUND){
1973 if (dhcp_timeout_reboot >= DHCP_TIMEOUT_TRIES_REBOOT) {
1974 dhcp_timeout_reboot = 0;
1975 aos_reboot(); // for the case that bk wifi state machine crash
1976 return;
1977 }
1978
1979 dhcp_cleanup(netif);
1980 sys_untimeout(dhcp_check_status, NULL);
1981 LWIP_DEBUGF(DHCP_DEBUG, ("dhcp timeout, bk_wlan_connection_loss\r\n"));
1982 bk_wlan_connection_loss();
1983 dhcp_timeout_reboot++;
1984 return;
1985 }
1986 }
1987
1988 netif = netif->next;
1989 }
1990 }
1991
dhcp_stop_timeout_check(void)1992 void dhcp_stop_timeout_check(void)
1993 {
1994 sys_untimeout(dhcp_check_status, NULL);
1995 }
1996
dhcp_start_timeout_check(u32_t secs)1997 void dhcp_start_timeout_check(u32_t secs)
1998 {
1999 sys_timeout(secs, dhcp_check_status, NULL);
2000 }
2001
2002
2003 #endif
2004
2005 #endif /* LWIP_IPV4 && LWIP_DHCP */
2006