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 LWIP_HOOK_DHCP_APPEND_OPTIONS
25 * @see LWIP_HOOK_DHCP_PARSE_OPTION
26 *
27 * @see netifapi_dhcp4
28 */
29
30 /*
31 * Copyright (c) 2001-2004 Leon Woestenberg <leon.woestenberg@gmx.net>
32 * Copyright (c) 2001-2004 Axon Digital Design B.V., The Netherlands.
33 * All rights reserved.
34 *
35 * Redistribution and use in source and binary forms, with or without modification,
36 * are permitted provided that the following conditions are met:
37 *
38 * 1. Redistributions of source code must retain the above copyright notice,
39 * this list of conditions and the following disclaimer.
40 * 2. Redistributions in binary form must reproduce the above copyright notice,
41 * this list of conditions and the following disclaimer in the documentation
42 * and/or other materials provided with the distribution.
43 * 3. The name of the author may not be used to endorse or promote products
44 * derived from this software without specific prior written permission.
45 *
46 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
47 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
48 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
49 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
50 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
51 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
52 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
53 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
54 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
55 * OF SUCH DAMAGE.
56 *
57 * This file is part of the lwIP TCP/IP stack.
58 * The Swedish Institute of Computer Science and Adam Dunkels
59 * are specifically granted permission to redistribute this
60 * source code.
61 *
62 * Author: Leon Woestenberg <leon.woestenberg@gmx.net>
63 *
64 */
65
66 #include "lwip/opt.h"
67
68 #if LWIP_IPV4 && LWIP_DHCP /* don't build if not configured for use in lwipopts.h */
69
70 #include "lwip/stats.h"
71 #include "lwip/mem.h"
72 #include "lwip/udp.h"
73 #include "lwip/ip_addr.h"
74 #include "lwip/netif.h"
75 #include "lwip/def.h"
76 #include "lwip/dhcp.h"
77 #include "lwip/autoip.h"
78 #include "lwip/dns.h"
79 #include "lwip/etharp.h"
80 #include "lwip/prot/dhcp.h"
81 #include "lwip/prot/iana.h"
82 #if LWIP_NAT64
83 #include "lwip/nat64_v4_dhcpc.h"
84 #include "lwip/nat64_addr.h"
85 #include "lwip/nat64.h"
86 #endif
87 #include <string.h>
88
89 #ifdef LWIP_HOOK_FILENAME
90 #include LWIP_HOOK_FILENAME
91 #endif
92 #ifndef LWIP_HOOK_DHCP_APPEND_OPTIONS
93 #define LWIP_HOOK_DHCP_APPEND_OPTIONS(netif, dhcp, state, msg, msg_type, options_len_ptr)
94 #endif
95 #ifndef LWIP_HOOK_DHCP_PARSE_OPTION
96 #define LWIP_HOOK_DHCP_PARSE_OPTION(netif, dhcp, state, msg, msg_type, option, len, pbuf, offset) do { LWIP_UNUSED_ARG(msg); } while(0)
97 #endif
98
99 /** DHCP_CREATE_RAND_XID: if this is set to 1, the xid is created using
100 * LWIP_RAND() (this overrides DHCP_GLOBAL_XID)
101 */
102 #ifndef DHCP_CREATE_RAND_XID
103 #define DHCP_CREATE_RAND_XID 1
104 #endif
105
106 #ifndef DHCP_REQUEST_TIMEOUT_DEFAULT
107 #define DHCP_REQUEST_TIMEOUT_DEFAULT 10 // 10 second
108 #endif
109
110 /** Default for DHCP_GLOBAL_XID is 0xABCD0000
111 * This can be changed by defining DHCP_GLOBAL_XID and DHCP_GLOBAL_XID_HEADER, e.g.
112 * \#define DHCP_GLOBAL_XID_HEADER "stdlib.h"
113 * \#define DHCP_GLOBAL_XID rand()
114 */
115 #ifdef DHCP_GLOBAL_XID_HEADER
116 #include DHCP_GLOBAL_XID_HEADER /* include optional starting XID generation prototypes */
117 #endif
118
119 /** Holds the decoded option values, only valid while in dhcp_recv.
120 @todo: move this into struct dhcp? */
121 u32_t dhcp_rx_options_val[DHCP_OPTION_IDX_MAX];
122 /** Holds a flag which option was received and is contained in dhcp_rx_options_val,
123 only valid while in dhcp_recv.
124 @todo: move this into struct dhcp? */
125 u8_t dhcp_rx_options_given[DHCP_OPTION_IDX_MAX];
126
127 static u8_t dhcp_discover_request_options[] = {
128 DHCP_OPTION_SUBNET_MASK,
129 DHCP_OPTION_ROUTER,
130 DHCP_OPTION_BROADCAST
131 #if LWIP_DHCP_PROVIDE_DNS_SERVERS
132 , DHCP_OPTION_DNS_SERVER
133 #endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS */
134 #if LWIP_DHCP_GET_NTP_SRV
135 , DHCP_OPTION_NTP
136 #endif /* LWIP_DHCP_GET_NTP_SRV */
137 };
138
139 #ifdef DHCP_GLOBAL_XID
140 static u32_t xid;
141 static u8_t xid_initialised;
142 #endif /* DHCP_GLOBAL_XID */
143
144 #if LWIP_DHCP_VENDOR_CLASS_IDENTIFIER
145 static struct vci_info g_vci_info = {{0}, 0};
146 #endif /* LWIP_DHCP_VENDOR_CLASS_IDENTIFIER */
147
148 #define dhcp_option_given(dhcp, idx) (dhcp_rx_options_given[idx] != 0)
149 #define dhcp_got_option(dhcp, idx) (dhcp_rx_options_given[idx] = 1)
150 #define dhcp_clear_option(dhcp, idx) (dhcp_rx_options_given[idx] = 0)
151 #define dhcp_clear_all_options(dhcp) (memset(dhcp_rx_options_given, 0, sizeof(dhcp_rx_options_given)))
152 #define dhcp_get_option_value(dhcp, idx) (dhcp_rx_options_val[idx])
153 #define dhcp_set_option_value(dhcp, idx, val) (dhcp_rx_options_val[idx] = (val))
154
155 static struct udp_pcb *dhcp_pcb;
156 #if LWIP_DHCP_SUBSTITUTE
157 static u16_t dhcp_pcb_refcount;
158 #define DHCP_REF_F "hu"
159
160 #if LWIP_DHCP_LIMIT_CONCURRENT_REQUESTS
161 static u16_t g_dhcp_max_concurrent_num = LWIP_DHCP_MAX_CONCURRENT_REQUESTS_NUM;
162 #endif
163 #else
164 static u8_t dhcp_pcb_refcount;
165 #define DHCP_REF_F "hhu"
166 #endif
167
168 static err_t dhcp_release_client(struct netif *netif, struct dhcp_client *dhcp);
169 static err_t dhcp_renew_client(struct netif *netif, struct dhcp_client *dhcp);
170 static void dhcp_stop_client(struct netif *netif, struct dhcp_client *dhcp);
171 #if LWIP_DHCP_SUBSTITUTE
172 static void dhcp_substitute_clients_restart(struct netif *netif, struct dhcp_client *dhcp);
173 static s32_t dhcp_addr_clients_check(struct dhcp *netif_dhcp, const ip4_addr_t *ipaddr);
174 #if LWIP_DHCP_LIMIT_CONCURRENT_REQUESTS
175 static u8_t dhcp_client_request_processing(u8_t state);
176 static void dhcp_concurrent_limit_wait_timeout(struct netif *netif, struct dhcp_client *dhcp);
177 static void dhcp_concurrent_num_update(struct dhcp_client *dhcp);
178 static err_t dhcp_concurrent_start_client(struct dhcp_client *dhcp);
179 static void dhcp_concurrent_stop_client(struct dhcp_client *dhcp);
180 static void dhcp_concurrent_start_next_client(struct netif *netif, u8_t all);
181 #endif
182 #endif /* LWIP_DHCP_SUBSTITUTE */
183
184 #if LWIP_DHCP_SUBSTITUTE_MMBR
185 static void dhcp_release_check(struct netif *netif, struct dhcp_client *dhcp);
186 #endif
187
188 /* DHCP client state machine functions */
189 static err_t dhcp_discover(struct netif *netif, struct dhcp_client *dhcp);
190 static err_t dhcp_select(struct netif *netif, struct dhcp_client *dhcp);
191 static void dhcp_bind(struct netif *netif, struct dhcp_client *dhcp);
192 #if LWIP_ARP
193 static void dhcp_announce(struct netif *netif, struct dhcp_client *dhcp);
194 #endif
195 #if DHCP_DOES_ARP_CHECK
196 static err_t dhcp_decline(struct netif *netif, struct dhcp_client *dhcp);
197 #endif /* DHCP_DOES_ARP_CHECK */
198 static err_t dhcp_rebind(struct netif *netif, struct dhcp_client *dhcp);
199 static err_t dhcp_reboot(struct netif *netif);
200 static void dhcp_set_state(struct dhcp_client *dhcp, u8_t new_state);
201
202 /* receive, unfold, parse and free incoming messages */
203 static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port);
204
205 /* set the DHCP timers */
206 static void dhcp_timeout(struct netif *netif, struct dhcp_client *dhcp);
207 static void dhcp_t1_timeout(struct netif *netif, struct dhcp_client *dhcp);
208 static void dhcp_t2_timeout(struct netif *netif, struct dhcp_client *dhcp);
209
210 /* build outgoing messages */
211 /* create a DHCP message, fill in common headers */
212 static err_t dhcp_create_msg(struct netif *netif, struct dhcp_client *dhcp, u8_t message_type, u16_t *options_out_len);
213 /* free a DHCP request */
214 static void dhcp_delete_msg(struct dhcp_client *dhcp);
215 /* add a DHCP option (type, then length in bytes) */
216 static u16_t dhcp_option(u16_t options_out_len, u8_t *options, u8_t option_type, u8_t option_len);
217 /* add option values */
218 static u16_t dhcp_option_byte(u16_t options_out_len, u8_t *options, u8_t value);
219 static u16_t dhcp_option_short(u16_t options_out_len, u8_t *options, u16_t value);
220 static u16_t dhcp_option_long(u16_t options_out_len, u8_t *options, u32_t value);
221 #if LWIP_NETIF_HOSTNAME
222 static u16_t dhcp_option_hostname(u16_t options_out_len, u8_t *options, struct netif *netif);
223 #endif /* LWIP_NETIF_HOSTNAME */
224
225 #if LWIP_DHCP_VENDOR_CLASS_IDENTIFIER
226 static u16_t dhcp_option_vci(u16_t options_out_len, u8_t *options, const struct netif *netif);
227 #endif /* LWIP_DHCP_VENDOR_CLASS_IDENTIFIER */
228
229 /* always add the DHCP options trailer to end and pad */
230 static void dhcp_option_trailer(u16_t options_out_len, u8_t *options, struct pbuf *p_out);
231
232 /** Ensure DHCP PCB is allocated and bound */
233 static err_t
dhcp_inc_pcb_refcount(u8_t ifindex)234 dhcp_inc_pcb_refcount(u8_t ifindex)
235 {
236 LWIP_DEBUGF_LOG1(DHCP_DEBUG | LWIP_DBG_TRACE, "dhcp_inc_pcb_refcount:enter %"DHCP_REF_F"\n", dhcp_pcb_refcount);
237 if (dhcp_pcb_refcount == 0) {
238 LWIP_ASSERT("dhcp_inc_pcb_refcount(): memory leak", dhcp_pcb == NULL);
239
240 /* allocate UDP PCB */
241 dhcp_pcb = udp_new();
242
243 if (dhcp_pcb == NULL) {
244 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, "dhcp_inc_pcb_refcount:udp new failed\n");
245 return ERR_MEM;
246 }
247
248 #if LWIP_SO_PRIORITY
249 dhcp_pcb->priority = LWIP_PKT_PRIORITY_DHCP;
250 #endif /* LWIP_SO_PRIORITY */
251
252 ip_set_option(dhcp_pcb, SOF_BROADCAST);
253 LWIP_UNUSED_ARG(ifindex);
254
255 /* set up local and remote port for the pcb -> listen on all interfaces on all src/dest IPs */
256 udp_bind(dhcp_pcb, IP4_ADDR_ANY, LWIP_IANA_PORT_DHCP_CLIENT);
257 udp_connect(dhcp_pcb, IP4_ADDR_ANY, LWIP_IANA_PORT_DHCP_SERVER);
258 udp_recv(dhcp_pcb, dhcp_recv, NULL);
259 }
260
261 dhcp_pcb_refcount++;
262 LWIP_DEBUGF_LOG1(DHCP_DEBUG | LWIP_DBG_TRACE, "dhcp_inc_pcb_refcount:leave %"DHCP_REF_F"\n", dhcp_pcb_refcount);
263
264 return ERR_OK;
265 }
266
267 /** Free DHCP PCB if the last netif stops using it */
268 static void
dhcp_dec_pcb_refcount(void)269 dhcp_dec_pcb_refcount(void)
270 {
271 LWIP_ASSERT("dhcp_pcb_refcount(): refcount error", (dhcp_pcb_refcount > 0));
272 LWIP_DEBUGF_LOG1(DHCP_DEBUG | LWIP_DBG_TRACE, "dhcp_dec_pcb_refcount:enter %"DHCP_REF_F"\n", dhcp_pcb_refcount);
273 dhcp_pcb_refcount--;
274
275 if (dhcp_pcb_refcount == 0) {
276 udp_remove(dhcp_pcb);
277 dhcp_pcb = NULL;
278 }
279 LWIP_DEBUGF_LOG1(DHCP_DEBUG | LWIP_DBG_TRACE, "dhcp_dec_pcb_refcount:leave %"DHCP_REF_F"\n", dhcp_pcb_refcount);
280 }
281
282 static void
dhcp_get_client_ip(u32_t * cli_ip,struct dhcp_client * dhcp,struct dhcp_state * dhcp_state)283 dhcp_get_client_ip(u32_t *cli_ip, struct dhcp_client *dhcp, struct dhcp_state *dhcp_state)
284 {
285 if (ip4_addr_isany_val(dhcp->relay_ip)) {
286 DHCP_HOST_TO_IP(*cli_ip, ip_2_ip4(&dhcp->server_ip_addr)->addr, dhcp->offered_sn_mask.addr,
287 dhcp_state->offered_ip_addr);
288 } else {
289 DHCP_HOST_TO_IP(*cli_ip, dhcp->relay_ip.addr, dhcp->offered_sn_mask.addr,
290 dhcp_state->offered_ip_addr);
291 }
292 }
293
294 static void
dhcp_ip_to_mask(ip4_addr_t * server_ip_addr,ip4_addr_t * sn_mask)295 dhcp_ip_to_mask(ip4_addr_t *server_ip_addr, ip4_addr_t *sn_mask)
296 {
297 u8_t first_octet = ip4_addr1(server_ip_addr);
298 if (first_octet <= IPV4_ADDRESS_PREFIX_CLASS_A) {
299 ip4_addr_set_u32(sn_mask, PP_HTONL(0xff000000UL));
300 } else if (first_octet >= IPV4_ADDRESS_PREFIX_CLASS_C) {
301 ip4_addr_set_u32(sn_mask, PP_HTONL(0xffffff00UL));
302 } else {
303 ip4_addr_set_u32(sn_mask, PP_HTONL(0xffff0000UL));
304 }
305
306 return;
307 }
308
309 static err_t
dhcp_mac_to_idx(struct netif * netif,const u8_t * hwaddr,u8_t hwaddr_len,dhcp_num_t * mac_idx)310 dhcp_mac_to_idx(struct netif *netif, const u8_t *hwaddr, u8_t hwaddr_len, dhcp_num_t *mac_idx)
311 {
312 if ((netif->hwaddr_len == hwaddr_len) && (memcmp(netif->hwaddr, hwaddr, hwaddr_len) == 0)) {
313 *mac_idx = LWIP_DHCP_NATIVE_IDX;
314 return ERR_OK;
315 }
316
317 #if LWIP_DHCP_SUBSTITUTE && LWIP_NAT64
318 return nat64_entry_mac_to_idx(hwaddr, hwaddr_len, mac_idx);
319 #else
320 return ERR_VAL;
321 #endif /* LWIP_DHCP_SUBSTITUTE && LWIP_NAT64 */
322 }
323
324 err_t
dhcp_idx_to_mac(struct netif * netif,dhcp_num_t mac_idx,u8_t * hwaddr,u8_t * hwaddr_len)325 dhcp_idx_to_mac(struct netif *netif, dhcp_num_t mac_idx,
326 u8_t *hwaddr, u8_t *hwaddr_len)
327 {
328 if ((hwaddr == NULL) || (hwaddr_len == NULL)) {
329 return ERR_VAL;
330 }
331 if (mac_idx == LWIP_DHCP_NATIVE_IDX) {
332 if (memcpy_s(hwaddr, NETIF_MAX_HWADDR_LEN, netif->hwaddr, NETIF_MAX_HWADDR_LEN) != EOK) {
333 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("dhcp_idx_to_mac:memcpy failed\n"));
334 return ERR_MEM;
335 }
336 *hwaddr_len = netif->hwaddr_len;
337 return ERR_OK;
338 }
339
340 #if LWIP_DHCP_SUBSTITUTE && LWIP_NAT64
341 u8_t hw_len = NETIF_MAX_HWADDR_LEN;
342 if (nat64_entry_idx_to_mac(mac_idx, hwaddr, &hw_len) == ERR_OK) {
343 *hwaddr_len = hw_len;
344 return ERR_OK;
345 }
346 #endif /* LWIP_DHCP_SUBSTITUTE && LWIP_NAT64 */
347 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("dhcp_idx_to_mac:not find in nat64\n"));
348 return ERR_VAL;
349 }
350
351 static err_t
dhcp_client_find_by_mac_idx(struct dhcp_client * dhcp,dhcp_num_t mac_idx,dhcp_num_t * cli_idx)352 dhcp_client_find_by_mac_idx(struct dhcp_client *dhcp, dhcp_num_t mac_idx, dhcp_num_t *cli_idx)
353 {
354 int i;
355
356 for (i = 0; i < DHCP_CLIENT_NUM; i++) {
357 if ((dhcp->states)[i].idx == mac_idx) {
358 *cli_idx = (dhcp_num_t)i;
359 return ERR_OK;
360 }
361 }
362
363 return ERR_VAL;
364 }
365
366 static err_t
dhcp_client_state_new(struct dhcp_client * dhcp,dhcp_num_t mac_idx,dhcp_num_t * cli_idx)367 dhcp_client_state_new(struct dhcp_client *dhcp, dhcp_num_t mac_idx, dhcp_num_t *cli_idx)
368 {
369 int i;
370
371 if (dhcp->cli_cnt == DHCP_CLIENT_NUM) {
372 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_client_state_new:max cnt\n"));
373 return ERR_VAL;
374 }
375
376 for (i = 1; i < DHCP_CLIENT_NUM; i++) {
377 if ((dhcp->states)[i].idx == 0) {
378 *cli_idx = (dhcp_num_t)i;
379 (dhcp->states)[i].idx = mac_idx;
380 return ERR_OK;
381 }
382 }
383
384 return ERR_VAL;
385 }
386
387 static void
dhcp_clients_count_update(struct dhcp_client * dhcp)388 dhcp_clients_count_update(struct dhcp_client *dhcp)
389 {
390 int i;
391 dhcp_num_t cnt = 0;
392
393 for (i = 0; i < DHCP_CLIENT_NUM; i++) {
394 if ((dhcp->states)[i].hwaddr_len != 0) {
395 cnt++;
396 }
397 }
398
399 dhcp->cli_cnt = cnt;
400 return;
401 }
402
403 /**
404 * Back-off the DHCP client (because of a received NAK response).
405 *
406 * Back-off the DHCP client because of a received NAK. Receiving a
407 * NAK means the client asked for something non-sensible, for
408 * example when it tries to renew a lease obtained on another network.
409 *
410 * We clear any existing set IP address and restart DHCP negotiation
411 * afresh (as per RFC2131 3.2.3).
412 *
413 * @param netif the netif under DHCP control
414 */
415 static void
dhcp_handle_nak(struct netif * netif,struct dhcp_client * dhcp)416 dhcp_handle_nak(struct netif *netif, struct dhcp_client *dhcp)
417 {
418 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_handle_nak(netif=%p) %s%"U16_F"\n",
419 (void *)netif, netif->name, (u16_t)netif->num));
420 /* Change to a defined state - set this before assigning the address
421 to ensure the callback can use dhcp_supplied_address() */
422 dhcp_set_state(dhcp, DHCP_STATE_BACKING_OFF);
423 /* remove IP address from interface (must no longer be used, as per RFC2131) */
424 if (dhcp->cli_idx == LWIP_DHCP_NATIVE_IDX) {
425 (void)netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4);
426 }
427 /* We can immediately restart discovery */
428 (void)dhcp_discover(netif, dhcp);
429 }
430
431 #if DHCP_DOES_ARP_CHECK
432 /**
433 * Checks if the offered IP address is already in use.
434 *
435 * It does so by sending an ARP request for the offered address and
436 * entering CHECKING state. If no ARP reply is received within a small
437 * interval, the address is assumed to be free for use by us.
438 *
439 * @param netif the netif under DHCP control
440 */
441 static void
dhcp_check(struct netif * netif,struct dhcp_client * dhcp)442 dhcp_check(struct netif *netif, struct dhcp_client *dhcp)
443 {
444 err_t result;
445 u16_t msecs;
446 struct dhcp_state *dhcp_state = &((dhcp->states)[dhcp->cli_idx]);
447 ip4_addr_t cli_ip;
448 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_check(netif=%p) %s\n", (void *)netif, netif->name));
449 dhcp_set_state(dhcp, DHCP_STATE_CHECKING);
450 dhcp_get_client_ip(&cli_ip.addr, dhcp, dhcp_state);
451 /* create an ARP query for the offered IP address, expecting that no host
452 responds, as the IP address should not be in use. */
453 result = etharp_query(netif, &cli_ip, NULL);
454 if (result != ERR_OK) {
455 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("dhcp_check: could not perform ARP query\n"));
456 }
457 if (dhcp_state->tries < 255) {
458 dhcp_state->tries++;
459 }
460 msecs = 500;
461 dhcp_state->request_timeout = (u16_t)((msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS);
462 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_check(): set request timeout %"U16_F" msecs\n", msecs));
463 }
464 #endif /* DHCP_DOES_ARP_CHECK */
465
466 /**
467 * Remember the configuration offered by a DHCP server.
468 *
469 * @param netif the netif under DHCP control
470 */
471 static void
dhcp_handle_offer(struct netif * netif,struct dhcp_client * dhcp)472 dhcp_handle_offer(struct netif *netif, struct dhcp_client *dhcp)
473 {
474 struct dhcp_state *dhcp_state = &((dhcp->states)[dhcp->cli_idx]);
475 ip4_addr_t cli_ip;
476 #if LWIP_DHCP_SUBSTITUTE_MMBR
477 dhcp_num_t offered_ip_addr;
478 #endif
479 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_handle_offer(netif=%p) %s%"U16_F"\n",
480 (void *)netif, netif->name, (u16_t)netif->num));
481 /* obtain the server address */
482 if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_SERVER_ID)) {
483 dhcp_state->request_timeout = 0; /* stop timer */
484
485 ip_addr_set_ip4_u32(&dhcp->server_ip_addr, lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_SERVER_ID)));
486 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_handle_offer(): server 0x%08"X32_F"\n",
487 ip4_addr_get_u32(ip_2_ip4(&dhcp->server_ip_addr))));
488 if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_SUBNET_MASK)) {
489 ip4_addr_set_u32(&dhcp->offered_sn_mask, lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_SUBNET_MASK)));
490 } else {
491 dhcp_ip_to_mask(ip_2_ip4(&dhcp->server_ip_addr), &dhcp->offered_sn_mask);
492 }
493 /* remember offered address */
494 ip4_addr_copy(cli_ip, dhcp->msg_in->yiaddr);
495 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_handle_offer(): offer for 0x%08"X32_F"\n",
496 ip4_addr_get_u32(&cli_ip)));
497 #if LWIP_DHCP_SUBSTITUTE_MMBR
498 offered_ip_addr = dhcp_state->offered_ip_addr;
499 #endif
500 DHCP_IP_TO_HOST(dhcp_state->offered_ip_addr, cli_ip.addr, dhcp->offered_sn_mask.addr);
501 #if LWIP_DHCP_SUBSTITUTE_MMBR
502 /* if offered IP is not same with the preferred IP, should do duplicate IP check */
503 if ((dhcp_state->addr_not_dup_check == lwIP_TRUE) && offered_ip_addr != dhcp_state->offered_ip_addr) {
504 dhcp_state->addr_not_dup_check = lwIP_FALSE;
505 }
506 #endif
507 ip4_addr_copy(dhcp->relay_ip, dhcp->msg_in->giaddr);
508 (void)dhcp_select(netif, dhcp);
509 } else {
510 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
511 ("dhcp_handle_offer(netif=%p) did not get server ID!\n", (void *)netif));
512 }
513 }
514
515 static void
dhcp_fill_options(struct netif * netif,struct dhcp_client * dhcp,u8_t message_type,u32_t opt_flags,u16_t * opts_len)516 dhcp_fill_options(struct netif *netif, struct dhcp_client *dhcp, u8_t message_type, u32_t opt_flags, u16_t *opts_len)
517 {
518 u8_t i;
519 ip4_addr_t cli_ip;
520 struct dhcp_state *dhcp_state = &((dhcp->states)[dhcp->cli_idx]);
521
522 if (opt_flags & GEN_FLG(MAX_MSG_SIZE)) {
523 *opts_len = dhcp_option(*opts_len, dhcp->msg_out->options, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
524 u16_t val = (dhcp_state->state == DHCP_STATE_REBOOTING) ?
525 (u16_t)DHCP_MAX_MSG_LEN_MIN_REQUIRED : DHCP_MAX_MSG_LEN(netif);
526 *opts_len = dhcp_option_short(*opts_len, dhcp->msg_out->options, val);
527 }
528
529 if (opt_flags & GEN_FLG(REQUESTED_IP)) {
530 /* MUST request the offered IP address */
531 *opts_len = dhcp_option(*opts_len, dhcp->msg_out->options, DHCP_OPTION_REQUESTED_IP, 4);
532 dhcp_get_client_ip(&cli_ip.addr, dhcp, dhcp_state);
533 *opts_len = dhcp_option_long(*opts_len, dhcp->msg_out->options, lwip_ntohl(ip4_addr_get_u32(&cli_ip)));
534 }
535
536 *opts_len = dhcp_option(*opts_len, dhcp->msg_out->options, DHCP_OPTION_CLIENT_ID, 1 + dhcp_state->hwaddr_len);
537 *opts_len = dhcp_option_byte(*opts_len, dhcp->msg_out->options, dhcp->msg_out->htype);
538 for (i = 0; i < dhcp_state->hwaddr_len; i++) {
539 *opts_len = dhcp_option_byte(*opts_len, dhcp->msg_out->options, dhcp->hwaddr[i]);
540 }
541
542 if (opt_flags & GEN_FLG(PARAMETER_REQUEST_LIST)) {
543 *opts_len = dhcp_option(*opts_len, dhcp->msg_out->options, DHCP_OPTION_PARAMETER_REQUEST_LIST,
544 LWIP_ARRAYSIZE(dhcp_discover_request_options));
545 for (i = 0; i < LWIP_ARRAYSIZE(dhcp_discover_request_options); i++) {
546 *opts_len = dhcp_option_byte(*opts_len, dhcp->msg_out->options, dhcp_discover_request_options[i]);
547 }
548 }
549
550 #if LWIP_NETIF_HOSTNAME
551 if ((message_type == DHCP_DISCOVER) ||
552 ((message_type == DHCP_REQUEST) && (dhcp_state->state != DHCP_STATE_REBOOTING))) {
553 *opts_len = dhcp_option_hostname(*opts_len, dhcp->msg_out->options, netif);
554 }
555 #endif /* LWIP_NETIF_HOSTNAME */
556
557 #if LWIP_DHCP_VENDOR_CLASS_IDENTIFIER
558 if ((message_type != DHCP_DECLINE) && (message_type != DHCP_RELEASE)) {
559 *opts_len = dhcp_option_vci(*opts_len, dhcp->msg_out->options, netif);
560 }
561 #endif /* LWIP_DHCP_VENDOR_CLASS_IDENTIFIER */
562 (void)message_type;
563 LWIP_HOOK_DHCP_APPEND_OPTIONS(netif, dhcp, DHCP_STATE_REQUESTING, dhcp->msg_out, DHCP_REQUEST, opts_len);
564 dhcp_option_trailer(*opts_len, dhcp->msg_out->options, dhcp->p_out);
565 }
566
567 /**
568 * Select a DHCP server offer out of all offers.
569 *
570 * Simply select the first offer received.
571 *
572 * @param netif the netif under DHCP control
573 * @return lwIP specific error (see error.h)
574 */
575 static err_t
dhcp_select(struct netif * netif,struct dhcp_client * dhcp)576 dhcp_select(struct netif *netif, struct dhcp_client *dhcp)
577 {
578 err_t result;
579 u16_t msecs;
580 u16_t options_out_len;
581 struct dhcp_state *dhcp_state = &((dhcp->states)[dhcp->cli_idx]);
582 #if LWIP_DHCP_REQUEST_UNICAST
583 ip_addr_t unicast_ip;
584 #endif
585
586 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_select(netif=%p) %s%"U16_F"\n", (void *)netif, netif->name,
587 (u16_t)netif->num));
588 dhcp_set_state(dhcp, DHCP_STATE_REQUESTING);
589
590 /* create and initialize the DHCP message header */
591 result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST, &options_out_len);
592 if (result == ERR_OK) {
593 options_out_len = dhcp_option(options_out_len, dhcp->msg_out->options, DHCP_OPTION_SERVER_ID, 4);
594 options_out_len = dhcp_option_long(options_out_len, dhcp->msg_out->options,
595 lwip_ntohl(ip4_addr_get_u32(ip_2_ip4(&dhcp->server_ip_addr))));
596 dhcp_fill_options(netif, dhcp, DHCP_REQUEST,
597 GEN_FLG(MAX_MSG_SIZE) | GEN_FLG(REQUESTED_IP) | GEN_FLG(PARAMETER_REQUEST_LIST), &options_out_len);
598
599 #if LWIP_DHCP_REQUEST_UNICAST
600 if (!ip4_addr_isany_val(dhcp->relay_ip)) {
601 ip_addr_set_ip4_u32_val(unicast_ip, ip4_addr_get_u32(&dhcp->relay_ip));
602 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_select: UNICAST relay\n"));
603 } else {
604 ip_addr_set_ip4_u32_val(unicast_ip, ip4_addr_get_u32(ip_2_ip4(&dhcp->server_ip_addr)));
605 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_select: UNICAST serv\n"));
606 }
607 result = udp_sendto_if_src(dhcp_pcb, dhcp->p_out, &unicast_ip, LWIP_IANA_PORT_DHCP_SERVER, netif, IP4_ADDR_ANY);
608 #else
609 /* send broadcast to any DHCP server */
610 result = udp_sendto_if_src(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, LWIP_IANA_PORT_DHCP_SERVER, netif, IP4_ADDR_ANY);
611 #endif
612 dhcp_delete_msg(dhcp);
613 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_select: REQUESTING\n"));
614 } else {
615 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("dhcp_select: could not allocate DHCP request\n"));
616 }
617 if (dhcp_state->tries < 255) {
618 dhcp_state->tries++;
619 }
620 msecs = (u16_t)((dhcp_state->tries < 6 ? 1 << dhcp_state->tries : 60) * 1000);
621 dhcp_state->request_timeout = (u16_t)((msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS);
622 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_select(): set request timeout %"U16_F" msecs\n", msecs));
623 return result;
624 }
625
626 static void
dhcp_client_coarse_tmr(struct netif * netif,struct dhcp_client * dhcp)627 dhcp_client_coarse_tmr(struct netif *netif, struct dhcp_client *dhcp)
628 {
629 struct dhcp_state *dhcp_state = &((dhcp->states)[dhcp->cli_idx]);
630
631 if ((dhcp_state->state == DHCP_STATE_OFF)) {
632 return;
633 }
634
635 /* compare lease time to expire timeout */
636 if ((dhcp->t0_timeout != 0) && (++dhcp_state->lease_used >= dhcp->t0_timeout)) {
637 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_coarse_tmr(): t0 timeout\n"));
638 /* this clients' lease time has expired */
639 if (dhcp->cli_idx == LWIP_DHCP_NATIVE_IDX) {
640 (void)dhcp_release(netif);
641 } else {
642 (void)dhcp_release_client(netif, dhcp);
643 }
644 (void)dhcp_discover(netif, dhcp);
645 /* timer is active (non zero), and triggers (zeroes) now? */
646 } else if ((dhcp->t2_timeout != 0) && (dhcp_state->lease_used >= dhcp->t2_timeout)) {
647 if ((dhcp_state->re_time == 0) || (dhcp_state->re_time-- != 1)) {
648 return;
649 }
650 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_coarse_tmr(): t2 timeout\n"));
651 /* this clients' rebind timeout triggered */
652 dhcp_t2_timeout(netif, dhcp);
653 /* timer is active (non zero), and triggers (zeroes) now */
654 } else if ((dhcp->t1_timeout != 0) && (dhcp_state->re_time != 0) && (dhcp_state->re_time-- == 1)) {
655 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_coarse_tmr(): t1 timeout\n"));
656 /* this clients' renewal timeout triggered */
657 dhcp_t1_timeout(netif, dhcp);
658 }
659
660 return;
661 }
662
663 static void
dhcp_netif_coarse_tmr(struct netif * netif,struct dhcp * netif_dhcp)664 dhcp_netif_coarse_tmr(struct netif *netif, struct dhcp *netif_dhcp)
665 {
666 struct dhcp_state *dhcp_state = NULL;
667 int i;
668 u8_t hwaddr_len;
669
670 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_netif_coarse_tmr()\n"));
671 for (i = 0; i < DHCP_CLIENT_NUM; i++) {
672 netif_dhcp->client.cli_idx = (dhcp_num_t)i;
673 dhcp_state = &((netif_dhcp->client.states)[i]);
674 if ((i != LWIP_DHCP_NATIVE_IDX) && (dhcp_state->idx == 0)) {
675 continue;
676 }
677 if (dhcp_idx_to_mac(netif, dhcp_state->idx, netif_dhcp->client.hwaddr, &hwaddr_len) != ERR_OK) {
678 LWIP_DEBUGF_LOG1(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
679 "dhcp_netif_coarse_tmr:idx %u to mac failed\n", dhcp_state->idx);
680 continue;
681 }
682 dhcp_state->hwaddr_len = hwaddr_len;
683 dhcp_client_coarse_tmr(netif, &(netif_dhcp->client));
684 }
685
686 return;
687 }
688
689 /**
690 * The DHCP timer that checks for lease renewal/rebind timeouts.
691 * Must be called once a minute (see @ref DHCP_COARSE_TIMER_SECS).
692 */
693 void
dhcp_coarse_tmr(void)694 dhcp_coarse_tmr(void)
695 {
696 struct netif *netif;
697 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_coarse_tmr()\n"));
698 /* iterate through all network interfaces */
699 NETIF_FOREACH(netif) {
700 /* only act on DHCP configured interfaces */
701 struct dhcp *netif_dhcp = netif_dhcp_data(netif);
702 if (netif_dhcp != NULL) {
703 dhcp_netif_coarse_tmr(netif, netif_dhcp);
704 }
705 }
706 }
707
708 #if LWIP_LOWPOWER
709 #include "lwip/lowpower.h"
710
711 static u32_t
dhcp_netif_coarse_tmr_tick(struct dhcp * netif_dhcp)712 dhcp_netif_coarse_tmr_tick(struct dhcp *netif_dhcp)
713 {
714 struct dhcp_state *dhcp_state = NULL;
715 struct dhcp_client *client = NULL;
716 s32_t i;
717 u32_t tick = 0;
718 u32_t val;
719 u16_t lease_used;
720
721 for (i = 0; i < DHCP_CLIENT_NUM; i++) {
722 dhcp_state = &((netif_dhcp->client.states)[i]);
723 if ((i != LWIP_DHCP_NATIVE_IDX) && (dhcp_state->idx == 0)) {
724 continue;
725 }
726 if ((dhcp_state->state == DHCP_STATE_OFF)) {
727 continue;
728 }
729
730 client = &(netif_dhcp->client);
731 lease_used = dhcp_state->lease_used;
732 if (client->t0_timeout > 0) {
733 if (client->t0_timeout > lease_used) {
734 val = client->t0_timeout - lease_used;
735 SET_TMR_TICK(tick, val);
736 } else {
737 SET_TMR_TICK(tick, 1);
738 }
739 }
740
741 if (client->t2_timeout > 0) {
742 if (client->t2_timeout > lease_used) {
743 val = (client->t2_timeout - lease_used);
744 SET_TMR_TICK(tick, val);
745 } else if (dhcp_state->re_time > 0) {
746 val = dhcp_state->re_time;
747 SET_TMR_TICK(tick, val);
748 } else {
749 SET_TMR_TICK(tick, 1);
750 }
751 }
752
753 if (dhcp_state->re_time > 0) {
754 val = dhcp_state->re_time;
755 SET_TMR_TICK(tick, val);
756 }
757 }
758
759 return tick;
760 }
761
762 u32_t
dhcp_coarse_tmr_tick(void)763 dhcp_coarse_tmr_tick(void)
764 {
765 struct netif *netif = netif_list;
766 u32_t tick = 0;
767 u32_t val;
768
769 while (netif != NULL) {
770 /* only act on DHCP configured interfaces */
771 struct dhcp *netif_dhcp = netif_dhcp_data(netif);
772 if (netif_dhcp == NULL) {
773 /* proceed to next netif */
774 netif = netif->next;
775 continue;
776 }
777 val = dhcp_netif_coarse_tmr_tick(netif_dhcp);
778 SET_TMR_TICK(tick, val);
779 /* proceed to next netif */
780 netif = netif->next;
781 }
782
783 LOWPOWER_DEBUG(("%s tmr tick: %u\n", __func__, tick));
784 return tick;
785 }
786
787 u32_t
dhcp_fine_tmr_tick(void)788 dhcp_fine_tmr_tick(void)
789 {
790 struct netif *netif = netif_list;
791 struct dhcp_state *dhcp_state = NULL;
792 int i;
793 u32_t tick = 0;
794 u32_t val;
795
796 /* loop through netif's */
797 while (netif != NULL) {
798 struct dhcp *netif_dhcp = netif_dhcp_data(netif);
799 if (netif_dhcp == NULL) {
800 netif = netif->next;
801 continue;
802 }
803
804 for (i = 0; i < DHCP_CLIENT_NUM; i++) {
805 dhcp_state = &((netif_dhcp->client.states)[i]);
806 if ((i != LWIP_DHCP_NATIVE_IDX) && (dhcp_state->idx == 0)) {
807 continue;
808 }
809 if (dhcp_state->request_timeout >= 1) {
810 val = dhcp_state->request_timeout;
811 SET_TMR_TICK(tick, val);
812 }
813 }
814 /* proceed to next network interface */
815 netif = netif->next;
816 }
817 LOWPOWER_DEBUG(("%s tmr tick: %d\n", __func__, tick));
818 return tick;
819 }
820 #endif /* LWIP_LOWPOWER */
821
822 static void
dhcp_client_fine_tmr(struct netif * netif,struct dhcp_client * dhcp)823 dhcp_client_fine_tmr(struct netif *netif, struct dhcp_client *dhcp)
824 {
825 struct dhcp_state *dhcp_state = &((dhcp->states)[dhcp->cli_idx]);
826 /* timer is active (non zero), and is about to trigger now */
827 if (dhcp_state->request_timeout > 1) {
828 dhcp_state->request_timeout--;
829 } else if (dhcp_state->request_timeout == 1) {
830 dhcp_state->request_timeout--;
831 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_fine_tmr(): request timeout\n"));
832 /* this client's request timeout triggered */
833 dhcp_timeout(netif, dhcp);
834 }
835 return;
836 }
837
838 static void
dhcp_netif_fine_tmr(struct netif * netif,struct dhcp * netif_dhcp)839 dhcp_netif_fine_tmr(struct netif *netif, struct dhcp *netif_dhcp)
840 {
841 struct dhcp_state *dhcp_state = NULL;
842 int i;
843 u8_t hwaddr_len;
844 for (i = 0; i < DHCP_CLIENT_NUM; i++) {
845 netif_dhcp->client.cli_idx = (dhcp_num_t)i;
846 dhcp_state = &((netif_dhcp->client.states)[i]);
847 if ((i != LWIP_DHCP_NATIVE_IDX) && (dhcp_state->idx == 0)) {
848 continue;
849 }
850 if (dhcp_idx_to_mac(netif, dhcp_state->idx, netif_dhcp->client.hwaddr, &hwaddr_len) != ERR_OK) {
851 LWIP_DEBUGF_LOG1(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
852 "dhcp_netif_fine_tmr:idx %u to mac failed\n", dhcp_state->idx);
853 continue;
854 }
855 dhcp_state->hwaddr_len = hwaddr_len;
856 dhcp_client_fine_tmr(netif, &(netif_dhcp->client));
857 }
858 return;
859 }
860
861 /**
862 * DHCP transaction timeout handling (this function must be called every 500ms,
863 * see @ref DHCP_FINE_TIMER_MSECS).
864 *
865 * A DHCP server is expected to respond within a short period of time.
866 * This timer checks whether an outstanding DHCP request is timed out.
867 */
868 void
dhcp_fine_tmr(void)869 dhcp_fine_tmr(void)
870 {
871 struct netif *netif;
872 /* loop through netif's */
873 NETIF_FOREACH(netif) {
874 struct dhcp *netif_dhcp = netif_dhcp_data(netif);
875 /* only act on DHCP configured interfaces */
876 if (netif_dhcp != NULL) {
877 dhcp_netif_fine_tmr(netif, netif_dhcp);
878 }
879 }
880 }
881
882 /**
883 * A DHCP negotiation transaction, or ARP request, has timed out.
884 *
885 * The timer that was started with the DHCP or ARP request has
886 * timed out, indicating no response was received in time.
887 *
888 * @param netif the netif under DHCP control
889 */
890 static void
dhcp_timeout(struct netif * netif,struct dhcp_client * dhcp)891 dhcp_timeout(struct netif *netif, struct dhcp_client *dhcp)
892 {
893 struct dhcp_state *dhcp_state = &((dhcp->states)[dhcp->cli_idx]);
894
895 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_timeout()\n"));
896 /* back-off period has passed, or server selection timed out */
897 if ((dhcp_state->state == DHCP_STATE_BACKING_OFF) || (dhcp_state->state == DHCP_STATE_SELECTING)) {
898 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_timeout(): restarting discovery\n"));
899 (void)dhcp_discover(netif, dhcp);
900 /* receiving the requested lease timed out */
901 } else if (dhcp_state->state == DHCP_STATE_REQUESTING) {
902 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
903 ("dhcp_timeout(): REQUESTING, DHCP request timed out\n"));
904 if (dhcp_state->tries <= 5) {
905 (void)dhcp_select(netif, dhcp);
906 } else {
907 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): REQUESTING timed out\n"));
908 if (dhcp->cli_idx == LWIP_DHCP_NATIVE_IDX) {
909 (void)dhcp_release(netif);
910 } else {
911 (void)dhcp_release_client(netif, dhcp);
912 }
913 (void)dhcp_discover(netif, dhcp);
914 }
915 #if DHCP_DOES_ARP_CHECK
916 /* received no ARP reply for the offered address (which is good) */
917 } else if (dhcp_state->state == DHCP_STATE_CHECKING) {
918 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): CHECKING timed out\n"));
919 if (dhcp_state->tries <= 1) {
920 dhcp_check(netif, dhcp);
921 /* no ARP replies on the offered address,
922 looks like the IP address is indeed free */
923 } else {
924 /* bind the interface to the offered address */
925 dhcp_bind(netif, dhcp);
926 }
927 #endif /* DHCP_DOES_ARP_CHECK */
928 #if LWIP_DHCP_SUBSTITUTE_MMBR
929 /* received no ARP reply for the releasing address (no other using this address) */
930 } else if (dhcp_state->state == DHCP_STATE_RELEASING) {
931 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): RELEASING timed out\n"));
932 if (dhcp_state->tries <= 1) {
933 dhcp_release_check(netif, dhcp);
934 } else {
935 /* no other MBR using this address, release it */
936 dhcp_stop_client(netif, dhcp);
937 }
938 #endif /* LWIP_DHCP_SUBSTITUTE_MMBR */
939 } else if (dhcp_state->state == DHCP_STATE_REBOOTING) {
940 if (dhcp_state->tries < REBOOT_TRIES) {
941 (void)dhcp_reboot(netif);
942 } else {
943 (void)dhcp_discover(netif, dhcp);
944 }
945 } else if (dhcp_state->state == DHCP_STATE_RENEWING) {
946 /* 5: send dhcp request package six times to renew its lease */
947 if (dhcp_state->tries <= 5) {
948 (void)dhcp_renew_client(netif, dhcp);
949 }
950 } else if (dhcp_state->state == DHCP_STATE_REBINDING) {
951 /* 5: send dhcp request package six times to Rebind with a DHCP server for an existing DHCP lease. */
952 if (dhcp_state->tries <= 5) {
953 (void)dhcp_rebind(netif, dhcp);
954 }
955 #if LWIP_ARP
956 } else if (dhcp_state->state == DHCP_STATE_BOUND) {
957 if (dhcp_state->tries < LWIP_DHCP_ANNOUNCE_NUM) {
958 dhcp_announce(netif, dhcp);
959 } else {
960 dhcp_state->tries = 0;
961 }
962 #endif
963 #if (LWIP_DHCP_SUBSTITUTE && LWIP_DHCP_LIMIT_CONCURRENT_REQUESTS)
964 } else if (dhcp_state->state == DHCP_STATE_LIMIT_WAIT) {
965 dhcp_concurrent_limit_wait_timeout(netif, dhcp);
966 #endif
967 }
968 }
969
970 /**
971 * The renewal period has timed out.
972 *
973 * @param netif the netif under DHCP control
974 */
975 static void
dhcp_t1_timeout(struct netif * netif,struct dhcp_client * dhcp)976 dhcp_t1_timeout(struct netif *netif, struct dhcp_client *dhcp)
977 {
978 struct dhcp_state *dhcp_state = &((dhcp->states)[dhcp->cli_idx]);
979
980 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_t1_timeout()\n"));
981 if ((dhcp_state->state == DHCP_STATE_REQUESTING) || (dhcp_state->state == DHCP_STATE_BOUND) ||
982 (dhcp_state->state == DHCP_STATE_RENEWING)) {
983 /* just retry to renew - note that the rebind timer (t2) will
984 * eventually time-out if renew tries fail. */
985 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_t1_timeout(): must renew\n"));
986 /* This slightly different to RFC2131: DHCPREQUEST will be sent from state
987 DHCP_STATE_RENEWING, not DHCP_STATE_BOUND */
988 (void)dhcp_renew_client(netif, dhcp);
989 /* Calculate next timeout */
990 if (((dhcp->t2_timeout - dhcp_state->lease_used) / 2) >=
991 ((60 + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS)) {
992 dhcp_state->re_time = (u16_t)((dhcp->t2_timeout - dhcp_state->lease_used) / 2);
993 } else {
994 dhcp_state->re_time = (u16_t)(dhcp->t2_timeout - dhcp_state->lease_used);
995 }
996 }
997 }
998
999 /**
1000 * The rebind period has timed out.
1001 *
1002 * @param netif the netif under DHCP control
1003 */
1004 static void
dhcp_t2_timeout(struct netif * netif,struct dhcp_client * dhcp)1005 dhcp_t2_timeout(struct netif *netif, struct dhcp_client *dhcp)
1006 {
1007 struct dhcp_state *dhcp_state = &((dhcp->states)[dhcp->cli_idx]);
1008
1009 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_t2_timeout()\n"));
1010 if ((dhcp_state->state == DHCP_STATE_REQUESTING) || (dhcp_state->state == DHCP_STATE_BOUND) ||
1011 (dhcp_state->state == DHCP_STATE_RENEWING) || (dhcp_state->state == DHCP_STATE_REBINDING)) {
1012 /* just retry to rebind */
1013 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_t2_timeout(): must rebind\n"));
1014 /* This slightly different to RFC2131: DHCPREQUEST will be sent from state
1015 DHCP_STATE_REBINDING, not DHCP_STATE_BOUND */
1016 (void)dhcp_rebind(netif, dhcp);
1017 /* Calculate next timeout */
1018 if (((dhcp->t0_timeout - dhcp_state->lease_used) / 2) >=
1019 ((60 + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS)) {
1020 dhcp_state->re_time = (u16_t)((dhcp->t0_timeout - dhcp_state->lease_used) / 2);
1021 }
1022 }
1023 }
1024
1025 /**
1026 * Handle a DHCP ACK packet
1027 *
1028 * @param netif the netif under DHCP control
1029 */
1030 static void
dhcp_handle_ack(struct netif * netif,struct dhcp_client * dhcp)1031 dhcp_handle_ack(struct netif *netif, struct dhcp_client *dhcp)
1032 {
1033 #if LWIP_DHCP_BOOTP_FILE
1034 struct dhcp *netif_dhcp = netif_dhcp_data(netif);
1035 #else
1036 (void)netif;
1037 #endif /* LWIP_DHCP_BOOTP_FILE */
1038 ip4_addr_t cli_ip;
1039 struct dhcp_state *dhcp_state = &((dhcp->states)[dhcp->cli_idx]);
1040
1041 #if LWIP_DHCP_PROVIDE_DNS_SERVERS || LWIP_DHCP_GET_NTP_SRV
1042 u8_t n;
1043 #endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS || LWIP_DHCP_GET_NTP_SRV */
1044 #if LWIP_DHCP_GET_NTP_SRV
1045 ip4_addr_t ntp_server_addrs[LWIP_DHCP_MAX_NTP_SERVERS];
1046 #endif
1047
1048 /* clear options we might not get from the ACK */
1049 ip4_addr_set_zero(&dhcp->offered_sn_mask);
1050 ip4_addr_set_zero(&dhcp->offered_gw_addr);
1051 #if LWIP_DHCP_BOOTP_FILE
1052 if (dhcp->cli_idx == LWIP_DHCP_NATIVE_IDX) {
1053 ip4_addr_set_zero(&netif_dhcp->offered_si_addr);
1054 }
1055 #endif /* LWIP_DHCP_BOOTP_FILE */
1056
1057 /* lease time given? */
1058 if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_LEASE_TIME)) {
1059 /* remember offered lease time */
1060 dhcp->offered_t0_lease = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_LEASE_TIME);
1061 }
1062 /* renewal period given? */
1063 if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_T1)) {
1064 /* remember given renewal period */
1065 dhcp->offered_t1_renew = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_T1);
1066 } else {
1067 /* calculate safe periods for renewal */
1068 dhcp->offered_t1_renew = dhcp->offered_t0_lease / 2;
1069 }
1070
1071 /* renewal period given? */
1072 if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_T2)) {
1073 /* remember given rebind period */
1074 dhcp->offered_t2_rebind = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_T2);
1075 } else {
1076 /* calculate safe periods for rebinding (offered_t0_lease * 0.875 -> 87.5%)*/
1077 dhcp->offered_t2_rebind = (dhcp->offered_t0_lease * 7U) / 8U;
1078 }
1079
1080 #if LWIP_DHCP_BOOTP_FILE
1081 /* copy boot server address,
1082 boot file name copied in dhcp_parse_reply if not overloaded */
1083 if (dhcp->cli_idx == LWIP_DHCP_NATIVE_IDX) {
1084 ip4_addr_copy(netif_dhcp->offered_si_addr, dhcp->msg_in->siaddr);
1085 }
1086 #endif /* LWIP_DHCP_BOOTP_FILE */
1087
1088 /* subnet mask given? */
1089 if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_SUBNET_MASK)) {
1090 /* remember given subnet mask */
1091 ip4_addr_set_u32(&dhcp->offered_sn_mask, lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_SUBNET_MASK)));
1092 dhcp->subnet_mask_given = lwIP_TRUE;
1093 } else {
1094 dhcp_ip_to_mask(ip_2_ip4(&dhcp->server_ip_addr), &dhcp->offered_sn_mask);
1095 dhcp->subnet_mask_given = lwIP_FALSE;
1096 }
1097
1098 /* (y)our internet address */
1099 ip4_addr_copy(cli_ip, dhcp->msg_in->yiaddr);
1100 DHCP_IP_TO_HOST(dhcp_state->offered_ip_addr, cli_ip.addr, dhcp->offered_sn_mask.addr);
1101
1102 /* gateway router */
1103 if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_ROUTER)) {
1104 ip4_addr_set_u32(&dhcp->offered_gw_addr, lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_ROUTER)));
1105 }
1106
1107 #if LWIP_DHCP_GET_NTP_SRV
1108 /* NTP servers */
1109 if (dhcp->cli_idx == LWIP_DHCP_NATIVE_IDX) {
1110 for (n = 0; (n < LWIP_DHCP_MAX_NTP_SERVERS) && dhcp_option_given(dhcp, DHCP_OPTION_IDX_NTP_SERVER + n); n++) {
1111 ip4_addr_set_u32(&ntp_server_addrs[n], lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_NTP_SERVER + n)));
1112 }
1113 dhcp_set_ntp_servers(n, ntp_server_addrs);
1114 }
1115 #endif /* LWIP_DHCP_GET_NTP_SRV */
1116
1117 #if LWIP_DNS
1118 #if LWIP_DHCP_PROVIDE_DNS_SERVERS
1119 /* DNS servers */
1120 if (dhcp->cli_idx == LWIP_DHCP_NATIVE_IDX) {
1121 for (n = 0; (n < LWIP_DHCP_PROVIDE_DNS_SERVERS) && dhcp_option_given(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n); n++) {
1122 ip_addr_t dns_addr;
1123 ip_addr_set_ip4_u32_val(dns_addr, lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n)));
1124 dns_setserver(n, &dns_addr);
1125 }
1126 }
1127 #endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS */
1128 #endif
1129 }
1130
1131 /**
1132 * @ingroup dhcp4
1133 * Set a statically allocated struct dhcp to work with.
1134 * Using this prevents dhcp_start to allocate it using mem_malloc.
1135 *
1136 * @param netif the netif for which to set the struct dhcp
1137 * @param dhcp (uninitialised) dhcp struct allocated by the application
1138 */
1139 void
dhcp_set_struct(struct netif * netif,struct dhcp * dhcp)1140 dhcp_set_struct(struct netif *netif, struct dhcp *dhcp)
1141 {
1142 LWIP_ASSERT_CORE_LOCKED();
1143 LWIP_ERROR("netif != NULL", (netif != NULL), return;);
1144 LWIP_ERROR("dhcp != NULL", (dhcp != NULL), return;);
1145
1146 /* clear data structure */
1147 memset(dhcp, 0, sizeof(struct dhcp));
1148 /* dhcp_set_state(&dhcp, DHCP_STATE_OFF); */
1149 netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP, dhcp);
1150 }
1151
1152 void
dhcp_remove_struct(struct netif * netif)1153 dhcp_remove_struct(struct netif *netif)
1154 {
1155 LWIP_ERROR("netif != NULL", (netif != NULL), return);
1156
1157 netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP, NULL);
1158 return;
1159 }
1160
1161 static void
dhcp_cleanup_indeed(void)1162 dhcp_cleanup_indeed(void)
1163 {
1164 if (dhcp_pcb != NULL) {
1165 udp_remove(dhcp_pcb);
1166 dhcp_pcb = NULL;
1167 }
1168 dhcp_pcb_refcount = 0;
1169 }
1170
1171 /**
1172 * @ingroup dhcp4
1173 * Removes a struct dhcp from a netif.
1174 *
1175 * ATTENTION: Only use this when not using dhcp_set_struct() to allocate the
1176 * struct dhcp since the memory is passed back to the heap.
1177 *
1178 * @param netif the netif from which to remove the struct dhcp
1179 */
dhcp_cleanup(struct netif * netif)1180 void dhcp_cleanup(struct netif *netif)
1181 {
1182 LWIP_ASSERT_CORE_LOCKED();
1183 struct dhcp *netif_dhcp = NULL;
1184 #if LWIP_DHCP_SUBSTITUTE
1185 int i;
1186 struct dhcp_client *dhcp = NULL;
1187 struct dhcp_state *dhcp_state = NULL;
1188 #endif /* LWIP_DHCP_SUBSTITUTE */
1189 LWIP_ERROR("netif != NULL", (netif != NULL), return);
1190
1191 netif_dhcp = netif_dhcp_data(netif);
1192 if (netif_dhcp == NULL) {
1193 return;
1194 }
1195 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_cleanup\n"));
1196 if (netif_dhcp->pcb_allocated != 0) {
1197 dhcp_stop(netif);
1198 }
1199 #if LWIP_DHCP_SUBSTITUTE
1200 dhcp = &(netif_dhcp->client);
1201 for (i = 1; i < DHCP_CLIENT_NUM; i++) {
1202 dhcp_state = &((dhcp->states)[i]);
1203 if (dhcp_state->idx == 0) {
1204 continue;
1205 }
1206 dhcp_substitute_stop(netif, dhcp_state->idx, lwIP_FALSE);
1207 }
1208 if (netif_dhcp->clis_info != NULL) {
1209 mem_free(netif_dhcp->clis_info);
1210 netif_dhcp->clis_info = NULL;
1211 }
1212 #endif /* LWIP_DHCP_SUBSTITUTE */
1213 dhcp_cleanup_indeed();
1214 mem_free(netif_dhcp_data(netif));
1215 netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP, NULL);
1216 }
1217
1218 /**
1219 * Check DHCP negotiation is done for a network interface.
1220 *
1221 * @param netif The lwIP network interface
1222 * @return
1223 * - ERR_OK - if DHCP is bound
1224 * - ERR_MEM - if DHCP bound is still progressing
1225 */
1226 err_t
dhcp_is_bound(struct netif * netif)1227 dhcp_is_bound(struct netif *netif)
1228 {
1229 struct dhcp *netif_dhcp = NULL;
1230
1231 LWIP_ERROR("netif != NULL", (netif != NULL), return ERR_ARG);
1232
1233 netif_dhcp = netif_dhcp_data(netif);
1234 LWIP_ERROR("netif->dhcp != NULL", (netif_dhcp != NULL), return ERR_ARG);
1235
1236 if ((netif_dhcp->client.states)[LWIP_DHCP_NATIVE_IDX].state == DHCP_STATE_BOUND) {
1237 return ERR_OK;
1238 } else {
1239 return ERR_INPROGRESS;
1240 }
1241 }
1242
1243 static void
dhcp_native_reset(struct dhcp * netif_dhcp)1244 dhcp_native_reset(struct dhcp *netif_dhcp)
1245 {
1246 netif_dhcp->pcb_allocated = 0;
1247 #if LWIP_DHCP_AUTOIP_COOP
1248 netif_dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF;
1249 #endif /* LWIP_DHCP_AUTOIP_COOP */
1250 #if LWIP_DHCP_BOOTP_FILE
1251 (void)memset_s(&(netif_dhcp->offered_si_addr), sizeof(netif_dhcp->offered_si_addr),
1252 0x0, sizeof(netif_dhcp->offered_si_addr));
1253 (void)memset_s(netif_dhcp->boot_file_name, sizeof(netif_dhcp->boot_file_name),
1254 0x0, sizeof(netif_dhcp->boot_file_name));
1255 #endif /* LWIP_DHCP_BOOTP_FILE */
1256
1257 return;
1258 }
1259
1260 static struct dhcp *
dhcp_netif_dhcp_new(void)1261 dhcp_netif_dhcp_new(void)
1262 {
1263 struct dhcp *netif_dhcp = NULL;
1264
1265 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_netif_dhcp_new(): starting new DHCP client\n"));
1266 netif_dhcp = (struct dhcp *)mem_malloc(sizeof(struct dhcp));
1267 if (netif_dhcp == NULL) {
1268 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_netif_dhcp_new(): could not allocate dhcp\n"));
1269 return NULL;
1270 }
1271
1272 (void)memset_s(netif_dhcp, sizeof(struct dhcp), 0x0, sizeof(struct dhcp));
1273
1274 return netif_dhcp;
1275 }
1276
1277 static err_t
dhcp_start_client_native(struct netif * netif)1278 dhcp_start_client_native(struct netif *netif)
1279 {
1280 struct dhcp *netif_dhcp = NULL;
1281 struct dhcp_client *dhcp = NULL;
1282
1283 netif_dhcp = netif_dhcp_data(netif);
1284 dhcp = &(netif_dhcp->client);
1285 (void)dhcp;
1286 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
1287 ("dhcp_start_client_native(): restarting DHCP configuration\n"));
1288 LWIP_ASSERT("pbuf p_out wasn't freed", dhcp->p_out == NULL);
1289 LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL);
1290
1291 if (netif_dhcp->pcb_allocated != 0) {
1292 dhcp_dec_pcb_refcount(); /* free DHCP PCB if not needed any more */
1293 }
1294 /* dhcp is cleared below, no need to reset flag */
1295 /* clear data structure */
1296 dhcp_native_reset(netif_dhcp);
1297
1298 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start_client_native(): starting DHCP configuration\n"));
1299
1300 if (dhcp_inc_pcb_refcount(netif->ifindex) != ERR_OK) { /* ensure DHCP PCB is allocated */
1301 dhcp_stop(netif);
1302 return ERR_MEM;
1303 }
1304 netif_dhcp->pcb_allocated = 1;
1305
1306 return ERR_OK;
1307 }
1308
1309 #if LWIP_DHCP_SUBSTITUTE_MMBR
1310 /*
1311 * substitute client start with a preferred IP, then
1312 * Discover message will carry Request IP option filling with the preferred IP
1313 * it will not do duplicate IP check
1314 */
1315 static void
dhcp_substitute_prefer_ip(struct dhcp_client * dhcp,u32_t pref_ipv4)1316 dhcp_substitute_prefer_ip(struct dhcp_client *dhcp, u32_t pref_ipv4)
1317 {
1318 ip4_addr_t cli_ip, netaddr;
1319 dhcp_num_t offered_ip_addr;
1320 struct dhcp_state *dhcp_state = &((dhcp->states)[dhcp->cli_idx]);
1321
1322 if (ip4_addr_isany_val(dhcp->offered_sn_mask)) {
1323 return;
1324 }
1325
1326 if (ip4_addr_isany_val(dhcp->relay_ip)) {
1327 netaddr.addr = ip_2_ip4(&dhcp->server_ip_addr)->addr;
1328 } else {
1329 netaddr.addr = dhcp->relay_ip.addr;
1330 }
1331 cli_ip.addr = pref_ipv4;
1332
1333 /* it also can be checkout that pref_ipv4 is 0 */
1334 if (!ip4_addr_netcmp(&cli_ip, &netaddr, &(dhcp->offered_sn_mask))) {
1335 return;
1336 }
1337
1338 DHCP_IP_TO_HOST(offered_ip_addr, pref_ipv4, dhcp->offered_sn_mask.addr);
1339 dhcp_state->offered_ip_addr = offered_ip_addr;
1340 dhcp_state->addr_not_dup_check = lwIP_TRUE;
1341
1342 return;
1343 }
1344 #endif
1345
1346 static err_t
dhcp_start_client(struct netif * netif,dhcp_num_t mac_idx,u32_t pref_ipv4)1347 dhcp_start_client(struct netif *netif, dhcp_num_t mac_idx, u32_t pref_ipv4)
1348 {
1349 struct dhcp *netif_dhcp = NULL;
1350 struct dhcp_client *dhcp = NULL;
1351 struct dhcp_state *dhcp_state = NULL;
1352 u8_t hwaddr_len;
1353 err_t result;
1354 #if LWIP_DHCP_SUBSTITUTE
1355 u8_t is_new = lwIP_FALSE;
1356 #endif /* LWIP_DHCP_SUBSTITUTE */
1357
1358 #if !(LWIP_DHCP_SUBSTITUTE && LWIP_DHCP_SUBSTITUTE_MMBR)
1359 (void)pref_ipv4;
1360 #endif
1361
1362 /* check MTU of the netif */
1363 if (netif->mtu < DHCP_MAX_MSG_LEN_MIN_REQUIRED) {
1364 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE,
1365 ("dhcp_start_client(): Cannot use this netif with DHCP: MTU is too small\n"));
1366 return ERR_MEM;
1367 }
1368
1369 netif_dhcp = netif_dhcp_data(netif);
1370 /* no DHCP client attached yet? */
1371 if (netif_dhcp == NULL) {
1372 netif_dhcp = dhcp_netif_dhcp_new();
1373 if (netif_dhcp == NULL) {
1374 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE, "dhcp_start_client:new dhcp failed\n");
1375 return ERR_MEM;
1376 }
1377 /* store this dhcp client in the netif */
1378 netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP, netif_dhcp);
1379 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start_client(): allocated dhcp"));
1380 /* already has DHCP client attached */
1381 }
1382 dhcp = &(netif_dhcp->client);
1383 if (dhcp_client_find_by_mac_idx(dhcp, mac_idx, &(dhcp->cli_idx)) != ERR_OK) {
1384 LWIP_DEBUGF_LOG1(DHCP_DEBUG | LWIP_DBG_TRACE, "dhcp_start_client(): client state not find for %u\n", mac_idx);
1385 if (dhcp_client_state_new(dhcp, mac_idx, &(dhcp->cli_idx)) != ERR_OK) {
1386 LWIP_DEBUGF_LOG1(DHCP_DEBUG | LWIP_DBG_TRACE, "dhcp_start_client(): no client state for %u\n", mac_idx);
1387 return ERR_MEM;
1388 } else {
1389 #if LWIP_DHCP_SUBSTITUTE
1390 LWIP_DEBUGF_LOG1(DHCP_DEBUG | LWIP_DBG_TRACE, "dhcp_start_client(): new client state for %u\n", mac_idx);
1391 is_new = lwIP_TRUE;
1392 #endif /* LWIP_DHCP_SUBSTITUTE */
1393 }
1394 }
1395 dhcp_state = &((dhcp->states)[dhcp->cli_idx]);
1396 if (dhcp_idx_to_mac(netif, dhcp_state->idx, dhcp->hwaddr, &hwaddr_len) != ERR_OK) {
1397 LWIP_DEBUGF_LOG1(DHCP_DEBUG | LWIP_DBG_TRACE, "dhcp_start_client(): no client state for %u\n", mac_idx);
1398 return ERR_MEM;
1399 }
1400 dhcp_state->hwaddr_len = hwaddr_len;
1401
1402 if (mac_idx == LWIP_DHCP_NATIVE_IDX) {
1403 result = dhcp_start_client_native(netif);
1404 if (result != ERR_OK) {
1405 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE, "dhcp_start_client:native failed\n");
1406 (void)memset_s(dhcp_state, sizeof(struct dhcp_state), 0, sizeof(struct dhcp_state));
1407 return result;
1408 }
1409 }
1410 #if LWIP_DHCP_SUBSTITUTE
1411 else {
1412 if ((is_new == lwIP_TRUE) && (dhcp_inc_pcb_refcount(netif->ifindex) != ERR_OK)) {
1413 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE, "dhcp_start_client:inc ref failed\n");
1414 (void)memset_s(dhcp_state, sizeof(struct dhcp_state), 0, sizeof(struct dhcp_state));
1415 return ERR_MEM;
1416 }
1417 #if LWIP_DHCP_SUBSTITUTE_MMBR
1418 dhcp_substitute_prefer_ip(dhcp, pref_ipv4);
1419 #endif
1420 }
1421 #if LWIP_DHCP_LIMIT_CONCURRENT_REQUESTS
1422 if (dhcp_concurrent_start_client(dhcp) != ERR_OK) {
1423 return ERR_OK;
1424 }
1425 #endif
1426 #endif /* LWIP_DHCP_SUBSTITUTE */
1427
1428 #if LWIP_DHCP_CHECK_LINK_UP
1429 if (!netif_is_link_up(netif)) {
1430 /* set state INIT and wait for dhcp_network_changed() to call dhcp_discover() */
1431 dhcp_set_state(dhcp, DHCP_STATE_INIT);
1432 return ERR_OK;
1433 }
1434 #endif
1435
1436 /* (re)start the DHCP negotiation */
1437 result = dhcp_discover(netif, dhcp);
1438 if (result != ERR_OK) {
1439 /* free resources allocated above */
1440 if (mac_idx == LWIP_DHCP_NATIVE_IDX) {
1441 dhcp_stop(netif);
1442 } else {
1443 dhcp_stop_client(netif, dhcp);
1444 }
1445 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE, "dhcp_start_client:discover failed\n");
1446 return ERR_MEM;
1447 }
1448
1449 return ERR_OK;
1450 }
1451
1452 /**
1453 * @ingroup dhcp4
1454 * Start DHCP negotiation for a network interface.
1455 *
1456 * If no DHCP client instance was attached to this interface,
1457 * a new client is created first. If a DHCP client instance
1458 * was already present, it restarts negotiation.
1459 *
1460 * @param netif The lwIP network interface
1461 * @return lwIP error code
1462 * - ERR_OK - No error
1463 * - ERR_MEM - Out of memory
1464 */
1465 err_t
dhcp_start(struct netif * netif)1466 dhcp_start(struct netif *netif)
1467 {
1468 err_t result;
1469
1470 LWIP_ASSERT_CORE_LOCKED();
1471 LWIP_ERROR("netif != NULL", (netif != NULL), return ERR_ARG;);
1472 LWIP_ERROR("netif is not up, old style port?", netif_is_up(netif), return ERR_ARG;);
1473
1474 netif_set_ipaddr(netif, IP4_ADDR_ANY4);
1475 netif_set_gw(netif, IP4_ADDR_ANY4);
1476 netif_set_netmask(netif, IP4_ADDR_ANY4);
1477
1478 LWIP_DEBUGF_LOG4(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
1479 "dhcp_start(netif=%p) %c%c%"U16_F"\n", (void *)netif, netif->name[0], netif->name[1],
1480 (u16_t)netif->num);
1481
1482 /* Remove the flag that says this netif is handled by DHCP,
1483 it is set when we succeeded starting. */
1484 netif->flags = (netif->flags & (~NETIF_FLAG_DHCP));
1485
1486 result = dhcp_start_client(netif, LWIP_DHCP_NATIVE_IDX, 0);
1487
1488 if (result != ERR_OK) {
1489 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE, "dhcp start failed\n");
1490 return result;
1491 }
1492
1493 dhcp_clients_count_update(&(netif_dhcp_data(netif)->client));
1494 /* Set the flag that says this netif is handled by DHCP. */
1495 netif->flags |= NETIF_FLAG_DHCP;
1496 return ERR_OK;
1497 }
1498
1499 /**
1500 * @ingroup dhcp4
1501 * Inform a DHCP server of our manual configuration.
1502 *
1503 * This informs DHCP servers of our fixed IP address configuration
1504 * by sending an INFORM message. It does not involve DHCP address
1505 * configuration, it is just here to be nice to the network.
1506 *
1507 * @param netif The lwIP network interface
1508 */
1509 void
dhcp_inform(struct netif * netif)1510 dhcp_inform(struct netif *netif)
1511 {
1512 err_t result, ret;
1513 u16_t options_out_len;
1514
1515 u8_t is_malloc = lwIP_FALSE;
1516 u16_t malloc_size;
1517 u8_t hwaddr_len;
1518 struct dhcp_state *dhcp_state = NULL;
1519 struct dhcp *netif_dhcp = NULL;
1520 struct dhcp_client *dhcp = NULL;
1521
1522 LWIP_ASSERT_CORE_LOCKED();
1523 LWIP_ERROR("netif != NULL", (netif != NULL), return;);
1524 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE, "dhcp_inform\n");
1525 if (dhcp_inc_pcb_refcount(netif->ifindex) != ERR_OK) { /* ensure DHCP PCB is allocated */
1526 return;
1527 }
1528
1529 netif_dhcp = netif_dhcp_data(netif);
1530 if (netif_dhcp != NULL) {
1531 dhcp = &(netif_dhcp->client);
1532 } else {
1533 malloc_size = (u16_t)(sizeof(struct dhcp_client) - (DHCP_CLIENT_NUM - 1) * sizeof(struct dhcp_state));
1534 dhcp = (struct dhcp_client *)mem_malloc(malloc_size);
1535 if (dhcp == NULL) {
1536 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_inform: malloc failed\n"));
1537 return;
1538 }
1539 (void)memset_s(dhcp, malloc_size, 0, malloc_size);
1540 is_malloc = lwIP_TRUE;
1541 }
1542
1543 dhcp->cli_idx = LWIP_DHCP_NATIVE_IDX;
1544 dhcp_state = &(dhcp->states[LWIP_DHCP_NATIVE_IDX]);
1545 dhcp_set_state(dhcp, DHCP_STATE_INFORMING);
1546 if (dhcp_idx_to_mac(netif, LWIP_DHCP_NATIVE_IDX, dhcp->hwaddr, &hwaddr_len) != ERR_OK) {
1547 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_inform: get mac failed\n"));
1548 dhcp_dec_pcb_refcount();
1549 if (is_malloc == lwIP_TRUE) {
1550 mem_free(dhcp);
1551 }
1552 return;
1553 }
1554 dhcp_state->hwaddr_len = hwaddr_len;
1555
1556 /* create and initialize the DHCP message header */
1557 result = dhcp_create_msg(netif, dhcp, DHCP_INFORM, &options_out_len);
1558 if (result == ERR_OK) {
1559 dhcp_fill_options(netif, dhcp, DHCP_INFORM, GEN_FLG(MAX_MSG_SIZE), &options_out_len);
1560
1561 ret = udp_sendto_if(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, LWIP_IANA_PORT_DHCP_SERVER, netif);
1562 (void)ret;
1563 LWIP_DEBUGF_LOG1(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, "dhcp_inform: INFORMING %d\n", ret);
1564 dhcp_delete_msg(dhcp);
1565 } else {
1566 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_inform: could not allocate DHCP request\n"));
1567 }
1568
1569 dhcp_dec_pcb_refcount(); /* delete DHCP PCB if not needed any more */
1570 if (is_malloc == lwIP_TRUE) {
1571 mem_free(dhcp);
1572 }
1573 }
1574
1575 /** Handle a possible change in the network configuration.
1576 *
1577 * This enters the REBOOTING state to verify that the currently bound
1578 * address is still valid.
1579 */
1580 static void
dhcp_network_changed_client(struct netif * netif,struct dhcp_client * dhcp)1581 dhcp_network_changed_client(struct netif *netif, struct dhcp_client *dhcp)
1582 {
1583 #if LWIP_DHCP_AUTOIP_COOP
1584 struct dhcp *netif_dhcp = netif_dhcp_data(netif);
1585 #endif /* LWIP_DHCP_AUTOIP_COOP */
1586 struct dhcp_state *dhcp_state = &((dhcp->states)[dhcp->cli_idx]);
1587
1588 LWIP_DEBUGF_LOG1(DHCP_DEBUG | LWIP_DBG_TRACE, "dhcp_network_changed_client:state %hhu\n", dhcp_state->state);
1589
1590 switch (dhcp_state->state) {
1591 case DHCP_STATE_REBINDING:
1592 case DHCP_STATE_RENEWING:
1593 case DHCP_STATE_BOUND:
1594 case DHCP_STATE_REBOOTING:
1595 dhcp_state->tries = 0;
1596 #if (LWIP_DHCP_SUBSTITUTE && LWIP_DHCP_LIMIT_CONCURRENT_REQUESTS)
1597 if (dhcp_concurrent_start_client(dhcp) != ERR_OK) {
1598 LWIP_DEBUGF_LOG1(DHCP_DEBUG | LWIP_DBG_TRACE, "dhcp_network_changed_client:up limit %hu\n",
1599 g_dhcp_max_concurrent_num);
1600 return;
1601 }
1602 #endif
1603 (void)dhcp_reboot(netif);
1604 break;
1605 case DHCP_STATE_OFF:
1606 /* stay off */
1607 break;
1608 default:
1609 /* INIT/REQUESTING/CHECKING/BACKING_OFF restart with new 'rid' because the
1610 state changes, SELECTING: continue with current 'rid' as we stay in the
1611 same state */
1612 #if LWIP_DHCP_AUTOIP_COOP
1613 if ((dhcp->cli_idx == LWIP_DHCP_NATIVE_IDX) &&
1614 (netif_dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON)) {
1615 (void)autoip_stop(netif);
1616 netif_dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF;
1617 }
1618 #endif /* LWIP_DHCP_AUTOIP_COOP */
1619 /* ensure we start with short timeouts, even if already discovering */
1620 dhcp_state->tries = 0;
1621 #if (LWIP_DHCP_SUBSTITUTE && LWIP_DHCP_LIMIT_CONCURRENT_REQUESTS)
1622 if (dhcp_concurrent_start_client(dhcp) != ERR_OK) {
1623 LWIP_DEBUGF_LOG1(DHCP_DEBUG | LWIP_DBG_TRACE, "dhcp_network_changed_client:up limit %hu\n",
1624 g_dhcp_max_concurrent_num);
1625 return;
1626 }
1627 #endif
1628 (void)dhcp_discover(netif, dhcp);
1629 break;
1630 }
1631 }
1632
1633 void
dhcp_network_changed(struct netif * netif)1634 dhcp_network_changed(struct netif *netif)
1635 {
1636 struct dhcp *netif_dhcp = netif_dhcp_data(netif);
1637 struct dhcp_client *dhcp = NULL;
1638 struct dhcp_state *dhcp_state = NULL;
1639
1640 int i;
1641 u8_t hwaddr_len;
1642 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_network_changed()\n"));
1643 if (netif_dhcp == NULL) {
1644 return;
1645 }
1646 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_network_changed() dhcp\n"));
1647
1648 dhcp = &(netif_dhcp->client);
1649 #if (LWIP_DHCP_SUBSTITUTE && LWIP_DHCP_LIMIT_CONCURRENT_REQUESTS)
1650 dhcp->rqst_cli_cnt = 0;
1651 #endif
1652 for (i = 0; i < DHCP_CLIENT_NUM; i++) {
1653 dhcp->cli_idx = (dhcp_num_t)i;
1654 dhcp_state = &((dhcp->states)[i]);
1655 if ((i != LWIP_DHCP_NATIVE_IDX) && (dhcp_state->idx == 0)) {
1656 continue;
1657 }
1658 if (dhcp_idx_to_mac(netif, dhcp_state->idx, dhcp->hwaddr, &hwaddr_len) != ERR_OK) {
1659 LWIP_DEBUGF_LOG1(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
1660 "dhcp_network_changed:idx %"DHCP_NUM_F" to mac failed\n", dhcp_state->idx);
1661 continue;
1662 }
1663 dhcp_state->hwaddr_len = hwaddr_len;
1664 dhcp_network_changed_client(netif, dhcp);
1665 }
1666 }
1667
1668 #if DHCP_DOES_ARP_CHECK
1669 /**
1670 * Match an ARP reply with the offered IP address:
1671 * check whether the offered IP address is not in use using ARP
1672 *
1673 * @param netif the network interface on which the reply was received
1674 * @param addr The IP address we received a reply from
1675 */
1676 void
dhcp_arp_reply(struct netif * netif,const ip4_addr_t * addr)1677 dhcp_arp_reply(struct netif *netif, const ip4_addr_t *addr)
1678 {
1679 struct dhcp *netif_dhcp = NULL;
1680 struct dhcp_client *dhcp = NULL;
1681 struct dhcp_state *dhcp_state = NULL;
1682 ip4_addr_t cli_ip;
1683 u8_t hwaddr_len;
1684 int i;
1685
1686 LWIP_ERROR("netif != NULL", (netif != NULL), return;);
1687 netif_dhcp = netif_dhcp_data(netif);
1688 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_arp_reply()\n"));
1689 /* is a DHCP client doing an ARP check? */
1690 if (netif_dhcp == NULL) {
1691 return;
1692 }
1693 dhcp = &(netif_dhcp->client);
1694 for (i = 0; i < DHCP_CLIENT_NUM; i++) {
1695 dhcp->cli_idx = (dhcp_num_t)i;
1696 dhcp_state = &((dhcp->states)[i]);
1697 if ((i != LWIP_DHCP_NATIVE_IDX) && (dhcp_state->idx == 0)) {
1698 continue;
1699 }
1700 if (
1701 #if LWIP_DHCP_SUBSTITUTE_MMBR
1702 (dhcp_state->state == DHCP_STATE_RELEASING) ||
1703 #endif
1704 (dhcp_state->state == DHCP_STATE_CHECKING)) {
1705 LWIP_DEBUGF_LOG1(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
1706 "dhcp_arp_reply(): CHECKING, arp reply for 0x%08"X32_F"\n",
1707 ip4_addr_get_u32(addr));
1708 /* did a host respond with the address we
1709 were offered by the DHCP server? */
1710 dhcp_get_client_ip(&cli_ip.addr, dhcp, dhcp_state);
1711 if (!ip4_addr_cmp(addr, &cli_ip)) {
1712 continue;
1713 }
1714 /* we will not accept the offered address */
1715 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING,
1716 ("dhcp_arp_reply(): arp reply matched with offered address, declining\n"));
1717 if (dhcp_idx_to_mac(netif, dhcp_state->idx, dhcp->hwaddr, &hwaddr_len) != ERR_OK) {
1718 LWIP_DEBUGF_LOG1(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
1719 "dhcp_arp_reply:idx %u to mac failed\n", dhcp_state->idx);
1720 return;
1721 }
1722 dhcp_state->hwaddr_len = hwaddr_len;
1723 #if LWIP_DHCP_SUBSTITUTE_MMBR
1724 if (dhcp_state->state == DHCP_STATE_RELEASING) {
1725 /* just think that there is a MBR using this address, do not send Release message by me */
1726 dhcp_set_state(dhcp, DHCP_STATE_OFF);
1727 dhcp_stop_client(netif, dhcp);
1728 } else
1729 #endif
1730 {
1731 (void)dhcp_decline(netif, dhcp);
1732 }
1733 return;
1734 }
1735 }
1736 }
1737
1738 /**
1739 * Decline an offered lease.
1740 *
1741 * Tell the DHCP server we do not accept the offered address.
1742 * One reason to decline the lease is when we find out the address
1743 * is already in use by another host (through ARP).
1744 *
1745 * @param netif the netif under DHCP control
1746 */
1747 static err_t
dhcp_decline(struct netif * netif,struct dhcp_client * dhcp)1748 dhcp_decline(struct netif *netif, struct dhcp_client *dhcp)
1749 {
1750 struct dhcp_state *dhcp_state = &((dhcp->states)[dhcp->cli_idx]);
1751 err_t result, ret;
1752 u16_t msecs;
1753 u16_t options_out_len;
1754
1755 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_decline()\n"));
1756 dhcp_set_state(dhcp, DHCP_STATE_BACKING_OFF);
1757 /* create and initialize the DHCP message header */
1758 result = dhcp_create_msg(netif, dhcp, DHCP_DECLINE, &options_out_len);
1759 if (result == ERR_OK) {
1760 options_out_len = dhcp_option(options_out_len, dhcp->msg_out->options, DHCP_OPTION_SERVER_ID, 4);
1761 options_out_len = dhcp_option_long(options_out_len, dhcp->msg_out->options,
1762 lwip_ntohl(ip4_addr_get_u32(ip_2_ip4(&dhcp->server_ip_addr))));
1763 dhcp_fill_options(netif, dhcp, DHCP_DECLINE, GEN_FLG(REQUESTED_IP), &options_out_len);
1764
1765 /* per section 4.4.4, broadcast DECLINE messages */
1766 ret = udp_sendto_if_src(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, LWIP_IANA_PORT_DHCP_SERVER, netif, IP4_ADDR_ANY);
1767 dhcp_delete_msg(dhcp);
1768 (void)ret;
1769 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_decline: BACKING OFF\n"));
1770 } else {
1771 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
1772 ("dhcp_decline: could not allocate DHCP request\n"));
1773 }
1774 if (dhcp_state->tries < 255) {
1775 dhcp_state->tries++;
1776 }
1777 msecs = DHCP_REQUEST_TIMEOUT_DEFAULT * MS_PER_SECOND;
1778 dhcp_state->request_timeout = (u16_t)((msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS);
1779 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_decline(): set request timeout %"U16_F" msecs\n", msecs));
1780 return result;
1781 }
1782 #endif /* DHCP_DOES_ARP_CHECK */
1783
1784
1785 /**
1786 * Start the DHCP process, discover a DHCP server.
1787 *
1788 * @param netif the netif under DHCP control
1789 */
1790 static err_t
dhcp_discover(struct netif * netif,struct dhcp_client * dhcp)1791 dhcp_discover(struct netif *netif, struct dhcp_client *dhcp)
1792 {
1793 #if LWIP_DHCP_AUTOIP_COOP
1794 struct dhcp *netif_dhcp = netif_dhcp_data(netif);
1795 #endif
1796 struct dhcp_state *dhcp_state = &((dhcp->states)[dhcp->cli_idx]);
1797 err_t result, ret;
1798 u16_t msecs;
1799 u16_t options_out_len;
1800 u32_t opt_flags = GEN_FLG(MAX_MSG_SIZE) | GEN_FLG(PARAMETER_REQUEST_LIST);
1801 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover()\n"));
1802 #if LWIP_DHCP_SUBSTITUTE_MMBR
1803 if (dhcp_state->addr_not_dup_check != lwIP_TRUE)
1804 #endif
1805 {
1806 dhcp_state->offered_ip_addr = 0;
1807 }
1808
1809 dhcp_set_state(dhcp, DHCP_STATE_SELECTING);
1810 /* create and initialize the DHCP message header */
1811 result = dhcp_create_msg(netif, dhcp, DHCP_DISCOVER, &options_out_len);
1812 if (result == ERR_OK) {
1813 #if LWIP_DHCP_SUBSTITUTE_MMBR
1814 if ((dhcp_state->addr_not_dup_check == lwIP_TRUE) && dhcp_state->offered_ip_addr != 0) {
1815 /* Request IP option with preferred IP */
1816 opt_flags |= GEN_FLG(REQUESTED_IP);
1817 }
1818 #endif
1819 dhcp_fill_options(netif, dhcp, DHCP_DISCOVER, opt_flags, &options_out_len);
1820 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: making request\n"));
1821
1822 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, LWIP_IANA_PORT_DHCP_SERVER)\n"));
1823 ret = udp_sendto_if_src(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, LWIP_IANA_PORT_DHCP_SERVER, netif, IP4_ADDR_ANY);
1824 (void)ret;
1825 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: deleting()ing\n"));
1826 dhcp_delete_msg(dhcp);
1827 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover: SELECTING\n"));
1828 } else {
1829 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
1830 ("dhcp_discover: could not allocate DHCP request\n"));
1831 }
1832 if (dhcp_state->tries < 255) {
1833 dhcp_state->tries++;
1834 }
1835 #if LWIP_DHCP_AUTOIP_COOP
1836 if ((dhcp->cli_idx == LWIP_DHCP_NATIVE_IDX) && (dhcp_state->tries >= LWIP_DHCP_AUTOIP_COOP_TRIES) &&
1837 (netif_dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_OFF)) {
1838 netif_dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_ON;
1839 autoip_start(netif);
1840 }
1841 #endif /* LWIP_DHCP_AUTOIP_COOP */
1842 msecs = (u16_t)((dhcp_state->tries < 6 ? (1UL << dhcp_state->tries) : 60) * DHCP_DISCOVER_RETRANSMIT_INTERVAL);
1843 dhcp_state->request_timeout = (u16_t)((msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS);
1844 LWIP_DEBUGF_LOG1(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
1845 "dhcp_discover(): set request timeout %"U16_F" msecs\n", msecs);
1846 return result;
1847 }
1848
1849 #if LWIP_ARP
1850 static void
dhcp_announce(struct netif * netif,struct dhcp_client * dhcp)1851 dhcp_announce(struct netif *netif, struct dhcp_client *dhcp)
1852 {
1853 err_t result;
1854 u16_t msecs;
1855 struct dhcp_state *dhcp_state = &((dhcp->states)[dhcp->cli_idx]);
1856 ip4_addr_t cli_ip;
1857 LWIP_DEBUGF_LOG3(DHCP_DEBUG | LWIP_DBG_TRACE, "dhcp_announce(netif=%p) %c%c\n", (void *)netif, (s16_t)netif->name[0],
1858 (s16_t)netif->name[1]);
1859 dhcp_get_client_ip(&cli_ip.addr, dhcp, dhcp_state);
1860 result = etharp_announce(netif, (const ip4_addr_t *)(&cli_ip));
1861 if (result != ERR_OK) {
1862 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("dhcp_announce: arp announce failed\n"));
1863 }
1864 if (dhcp_state->tries < 255) {
1865 dhcp_state->tries++;
1866 }
1867 msecs = LWIP_DHCP_ANNOUNCE_INTERVAL * MS_PER_SECOND;
1868 dhcp_state->request_timeout = (u16_t)((msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS);
1869 LWIP_DEBUGF_LOG1(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, "dhcp_announce: set request timeout %"U16_F" msecs\n",
1870 msecs);
1871 }
1872 #endif
1873
1874 /**
1875 * Bind the interface to the offered IP address.
1876 *
1877 * @param netif network interface to bind to the offered address
1878 */
1879 static void
dhcp_bind(struct netif * netif,struct dhcp_client * dhcp)1880 dhcp_bind(struct netif *netif, struct dhcp_client *dhcp)
1881 {
1882 u32_t timeout;
1883 struct dhcp *netif_dhcp = NULL;
1884 ip4_addr_t sn_mask, gw_addr;
1885 u8_t is_native = lwIP_FALSE;
1886 ip4_addr_t cli_ip;
1887 struct dhcp_state *dhcp_state = NULL;
1888 #if (LWIP_DHCP_SUBSTITUTE && LWIP_DHCP_LIMIT_CONCURRENT_REQUESTS)
1889 dhcp_state_enum_t pre_state;
1890 #endif
1891 LWIP_ERROR("dhcp_bind: netif != NULL", (netif != NULL), return;);
1892 netif_dhcp = netif_dhcp_data(netif);
1893 LWIP_ERROR("dhcp_bind: netif_dhcp != NULL", (netif_dhcp != NULL), return;);
1894 LWIP_DEBUGF_LOG3(DHCP_DEBUG | LWIP_DBG_TRACE,
1895 "dhcp_bind(netif=%p) %s%"U16_F"\n", (void *)netif, netif->name, (u16_t)netif->num);
1896
1897 if (dhcp->cli_idx == LWIP_DHCP_NATIVE_IDX) {
1898 is_native = lwIP_TRUE;
1899 }
1900 dhcp_state = &((dhcp->states)[dhcp->cli_idx]);
1901 /* reset time used of lease */
1902 dhcp_state->lease_used = 0;
1903
1904 if (dhcp->offered_t0_lease != 0xffffffffUL) {
1905 /* set renewal period timer */
1906 LWIP_DEBUGF_LOG1(DHCP_DEBUG | LWIP_DBG_TRACE, "dhcp_bind(): t0 renewal timer %"U32_F" secs\n",
1907 dhcp->offered_t0_lease);
1908 timeout = (dhcp->offered_t0_lease + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS;
1909 if (timeout > 0xffff) {
1910 timeout = 0xffff;
1911 }
1912 dhcp->t0_timeout = (u16_t)timeout;
1913 if (dhcp->t0_timeout == 0) {
1914 dhcp->t0_timeout = 1;
1915 }
1916 LWIP_DEBUGF_LOG1(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
1917 "dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t0_lease * 1000);
1918 }
1919
1920 /* temporary DHCP lease? */
1921 if (dhcp->offered_t1_renew != 0xffffffffUL) {
1922 /* set renewal period timer */
1923 LWIP_DEBUGF_LOG1(DHCP_DEBUG | LWIP_DBG_TRACE, "dhcp_bind(): t1 renewal timer %"U32_F" secs\n",
1924 dhcp->offered_t1_renew);
1925 timeout = (dhcp->offered_t1_renew + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS;
1926 if (timeout > 0xffff) {
1927 timeout = 0xffff;
1928 }
1929 dhcp->t1_timeout = (u16_t)timeout;
1930 if (dhcp->t1_timeout == 0) {
1931 dhcp->t1_timeout = 1;
1932 }
1933 LWIP_DEBUGF_LOG1(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
1934 "dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t1_renew * 1000);
1935 dhcp_state->re_time = dhcp->t1_timeout;
1936 }
1937 /* set renewal period timer */
1938 if (dhcp->offered_t2_rebind != 0xffffffffUL) {
1939 LWIP_DEBUGF_LOG1(DHCP_DEBUG | LWIP_DBG_TRACE, "dhcp_bind(): t2 rebind timer %"U32_F" secs\n",
1940 dhcp->offered_t2_rebind);
1941 timeout = (dhcp->offered_t2_rebind + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS;
1942 if (timeout > 0xffff) {
1943 timeout = 0xffff;
1944 }
1945 dhcp->t2_timeout = (u16_t)timeout;
1946 if (dhcp->t2_timeout == 0) {
1947 dhcp->t2_timeout = 1;
1948 }
1949 LWIP_DEBUGF_LOG1(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
1950 "dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t2_rebind * 1000);
1951 }
1952
1953 /* If we have sub 1 minute lease, t2 and t1 will kick in at the same time. */
1954 if ((dhcp->t1_timeout >= dhcp->t2_timeout) && (dhcp->t2_timeout > 0)) {
1955 dhcp->t1_timeout = 0;
1956 dhcp_state->re_time = dhcp->t2_timeout;
1957 }
1958
1959 if (dhcp->subnet_mask_given == lwIP_TRUE) {
1960 /* copy offered network mask */
1961 ip4_addr_copy(sn_mask, dhcp->offered_sn_mask);
1962 } else {
1963 /* subnet mask not given, choose a safe subnet mask given the network class */
1964 dhcp_ip_to_mask(ip_2_ip4(&dhcp->server_ip_addr), &sn_mask);
1965 ip4_addr_copy(dhcp->offered_sn_mask, sn_mask);
1966 }
1967
1968 dhcp_get_client_ip(&cli_ip.addr, dhcp, dhcp_state);
1969
1970 ip4_addr_copy(gw_addr, dhcp->offered_gw_addr);
1971
1972 #if LWIP_DHCP_AUTOIP_COOP
1973 if ((is_native == lwIP_TRUE) && (netif_dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON)) {
1974 autoip_stop(netif);
1975 netif_dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF;
1976 }
1977 #endif /* LWIP_DHCP_AUTOIP_COOP */
1978
1979 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",
1980 ip4_addr_get_u32(&cli_ip), ip4_addr_get_u32(&sn_mask), ip4_addr_get_u32(&gw_addr)));
1981 #if (LWIP_DHCP_SUBSTITUTE && LWIP_DHCP_LIMIT_CONCURRENT_REQUESTS)
1982 pre_state = dhcp_state->state;
1983 #endif
1984 /* netif is now bound to DHCP leased address - set this before assigning the address
1985 to ensure the callback can use dhcp_supplied_address() */
1986 dhcp_set_state(dhcp, DHCP_STATE_BOUND);
1987
1988 if (is_native == lwIP_TRUE) {
1989 (void)netif_set_addr(netif, &cli_ip, &sn_mask, &gw_addr);
1990 }
1991 #if LWIP_NAT64
1992 else {
1993 nat64_dhcp_ip4_event(dhcp->hwaddr, dhcp_state->hwaddr_len, &cli_ip, NAT64_DHCP_EVENT_OFFER);
1994 }
1995 #endif
1996 #if LWIP_ARP
1997 if ((netif->flags & NETIF_FLAG_ETHARP) != 0) {
1998 dhcp_announce(netif, dhcp);
1999 }
2000 #endif
2001
2002 #if (LWIP_DHCP_SUBSTITUTE && LWIP_DHCP_LIMIT_CONCURRENT_REQUESTS)
2003 if ((g_dhcp_max_concurrent_num != 0) && (dhcp_client_request_processing(pre_state) == lwIP_TRUE)) {
2004 dhcp->rqst_cli_cnt--;
2005 dhcp_concurrent_start_next_client(netif, lwIP_FALSE);
2006 }
2007 #endif
2008 }
2009
2010 /* handle dhcp renew, rebind, reboot -- hence the name */
2011 static err_t
dhcp_re3(struct netif * netif,struct dhcp_client * dhcp,u8_t state)2012 dhcp_re3(struct netif *netif, struct dhcp_client *dhcp, u8_t state)
2013 {
2014 err_t result, ret;
2015 u16_t options_out_len;
2016 u16_t msecs;
2017 struct dhcp_state *dhcp_state = &((dhcp->states)[dhcp->cli_idx]);
2018
2019 dhcp_set_state(dhcp, state);
2020
2021 /* create and initialize the DHCP message header */
2022 result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST, &options_out_len);
2023 if (result == ERR_OK) {
2024 u32_t opt_flags = GEN_FLG(MAX_MSG_SIZE) | GEN_FLG(PARAMETER_REQUEST_LIST);
2025 if (state == DHCP_STATE_REBOOTING) {
2026 opt_flags |= GEN_FLG(REQUESTED_IP);
2027 }
2028 dhcp_fill_options(netif, dhcp, DHCP_REQUEST, opt_flags, &options_out_len);
2029
2030 const ip_addr_t *server_ip_addr = (state == DHCP_STATE_RENEWING) ?
2031 (&dhcp->server_ip_addr) : IP_ADDR_BROADCAST;
2032 ret = udp_sendto_if(dhcp_pcb, dhcp->p_out, server_ip_addr, LWIP_IANA_PORT_DHCP_SERVER, netif);
2033 (void)ret;
2034
2035 dhcp_delete_msg(dhcp);
2036
2037 LWIP_DEBUGF_LOG2(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, "dhcp_re3: state=%u ret %d\n", state, ret);
2038 } else {
2039 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
2040 ("dhcp_re3: could not allocate DHCP request\n"));
2041 }
2042 if (dhcp_state->tries < 255) {
2043 dhcp_state->tries++;
2044 }
2045 /* back-off on retries, but to a maximum of 20 seconds for RENEW, 10 seccond for others */
2046 msecs = (u16_t)(dhcp_state->tries < 10 ? dhcp_state->tries * 1000 : 10 * 1000);
2047 if (state == DHCP_STATE_RENEWING) {
2048 msecs *= 2U;
2049 }
2050 dhcp_state->request_timeout = (u16_t)((msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS);
2051 LWIP_DEBUGF_LOG1(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
2052 "dhcp_re3: set request timeout %"U16_F" msecs\n", msecs);
2053
2054 return result;
2055 }
2056
2057 static err_t
dhcp_renew_client(struct netif * netif,struct dhcp_client * dhcp)2058 dhcp_renew_client(struct netif *netif, struct dhcp_client *dhcp)
2059 {
2060 return dhcp_re3(netif, dhcp, DHCP_STATE_RENEWING);
2061 }
2062
2063 /**
2064 * @ingroup dhcp4
2065 * Renew an existing DHCP lease at the involved DHCP server.
2066 *
2067 * @param netif network interface which must renew its lease
2068 */
2069 err_t
dhcp_renew(struct netif * netif)2070 dhcp_renew(struct netif *netif)
2071 {
2072 struct dhcp *netif_dhcp = NULL;
2073 struct dhcp_state *dhcp_state = NULL;
2074 u8_t hwaddr_len;
2075
2076 LWIP_ASSERT_CORE_LOCKED();
2077 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_renew()\n"));
2078 LWIP_ERROR("netif != NULL", (netif != NULL), return ERR_ARG);
2079
2080 netif_dhcp = netif_dhcp_data(netif);
2081 LWIP_ERROR("netif != NULL", (netif_dhcp != NULL), return ERR_VAL);
2082 netif_dhcp->client.cli_idx = LWIP_DHCP_NATIVE_IDX;
2083 dhcp_state = &((netif_dhcp->client.states)[LWIP_DHCP_NATIVE_IDX]);
2084
2085 if (dhcp_idx_to_mac(netif, LWIP_DHCP_NATIVE_IDX, netif_dhcp->client.hwaddr, &hwaddr_len) != ERR_OK) {
2086 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_renew():get mac failed\n"));
2087 return ERR_VAL;
2088 }
2089 dhcp_state->hwaddr_len = hwaddr_len;
2090
2091 return dhcp_renew_client(netif, &(netif_dhcp->client));
2092 }
2093
2094 /**
2095 * Rebind with a DHCP server for an existing DHCP lease.
2096 *
2097 * @param netif network interface which must rebind with a DHCP server
2098 */
2099 static err_t
dhcp_rebind(struct netif * netif,struct dhcp_client * dhcp)2100 dhcp_rebind(struct netif *netif, struct dhcp_client *dhcp)
2101 {
2102 return dhcp_re3(netif, dhcp, DHCP_STATE_REBINDING);
2103 }
2104
2105 /**
2106 * Enter REBOOTING state to verify an existing lease
2107 *
2108 * @param netif network interface which must reboot
2109 */
2110 static err_t
dhcp_reboot(struct netif * netif)2111 dhcp_reboot(struct netif *netif)
2112 {
2113 struct dhcp_client *dhcp = &(netif_dhcp_data(netif)->client);
2114 return dhcp_re3(netif, dhcp, DHCP_STATE_REBOOTING);
2115 }
2116
2117 void
dhcp_release_and_stop(struct netif * netif)2118 dhcp_release_and_stop(struct netif *netif)
2119 {
2120 dhcp_stop(netif);
2121 }
2122
2123 /**
2124 * @ingroup dhcp4
2125 * Release a DHCP lease (usually called before @ref dhcp_stop).
2126 *
2127 * @param netif network interface which must release its lease
2128 */
2129 static err_t
dhcp_release_client(struct netif * netif,struct dhcp_client * dhcp)2130 dhcp_release_client(struct netif *netif, struct dhcp_client *dhcp)
2131 {
2132 err_t result, ret;
2133 ip_addr_t server_ip_addr;
2134 u16_t options_out_len = 0;
2135
2136 struct dhcp_state *dhcp_state = &((dhcp->states)[dhcp->cli_idx]);
2137 ip_addr_copy(server_ip_addr, dhcp->server_ip_addr);
2138
2139 dhcp_state->lease_used = 0;
2140
2141 if (dhcp->cli_cnt == 1) {
2142 dhcp->offered_t0_lease = dhcp->offered_t1_renew = dhcp->offered_t2_rebind = 0;
2143 dhcp->t0_timeout = 0;
2144 dhcp->t1_timeout = 0;
2145 dhcp->t2_timeout = 0;
2146 }
2147
2148 if (!((dhcp_state->state == DHCP_STATE_BOUND) ||
2149 (dhcp_state->state == DHCP_STATE_RENEWING) ||
2150 (dhcp_state->state == DHCP_STATE_REBINDING) ||
2151 (dhcp_state->state == DHCP_STATE_RELEASING))) {
2152 /* clean old DHCP offer */
2153 if (dhcp->cli_cnt == 1) {
2154 ip_addr_set_zero_ip4(&dhcp->server_ip_addr);
2155 ip4_addr_set_zero(&dhcp->offered_sn_mask);
2156 ip4_addr_set_zero(&dhcp->offered_gw_addr);
2157 ip4_addr_set_zero(&dhcp->relay_ip);
2158 }
2159 dhcp_state->offered_ip_addr = 0;
2160 /* don't issue release message when address is not dhcp-assigned */
2161 return ERR_OK;
2162 }
2163
2164 /* idle DHCP client */
2165 dhcp_set_state(dhcp, DHCP_STATE_OFF);
2166 /* create and initialize the DHCP message header */
2167 result = dhcp_create_msg(netif, dhcp, DHCP_RELEASE, &options_out_len);
2168 if (result == ERR_OK) {
2169 options_out_len = dhcp_option(options_out_len, dhcp->msg_out->options, DHCP_OPTION_SERVER_ID, 4);
2170 options_out_len = dhcp_option_long(options_out_len, dhcp->msg_out->options,
2171 lwip_ntohl(ip4_addr_get_u32(ip_2_ip4(&dhcp->server_ip_addr))));
2172 dhcp_fill_options(netif, dhcp, DHCP_RELEASE, 0, &options_out_len);
2173 ret = udp_sendto_if(dhcp_pcb, dhcp->p_out, &server_ip_addr, LWIP_IANA_PORT_DHCP_SERVER, netif);
2174 (void)ret;
2175 dhcp_delete_msg(dhcp);
2176 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_release: RELEASED, DHCP_STATE_OFF\n"));
2177 } else {
2178 /* sending release failed, but that's not a problem since the correct behaviour of dhcp does not rely on release */
2179 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
2180 ("dhcp_release: could not allocate DHCP request\n"));
2181 }
2182 /* clean old DHCP offer */
2183 if (dhcp->cli_cnt == 1) {
2184 ip_addr_set_zero_ip4(&dhcp->server_ip_addr);
2185 ip4_addr_set_zero(&dhcp->offered_sn_mask);
2186 ip4_addr_set_zero(&dhcp->offered_gw_addr);
2187 ip4_addr_set_zero(&dhcp->relay_ip);
2188 }
2189 dhcp_state->offered_ip_addr = 0;
2190 #if LWIP_NAT64
2191 nat64_dhcp_ip4_event(dhcp->hwaddr, dhcp_state->hwaddr_len, NULL, NAT64_DHCP_EVENT_RELEASE);
2192 #endif
2193
2194 return result;
2195 }
2196
2197
2198 /**
2199 * @ingroup dhcp4
2200 * Release a DHCP lease (usually called before @ref dhcp_stop).
2201 *
2202 * @param netif network interface which must release its lease
2203 */
2204 err_t
dhcp_release(struct netif * netif)2205 dhcp_release(struct netif *netif)
2206 {
2207 err_t result;
2208 struct dhcp *netif_dhcp = NULL;
2209 struct dhcp_state *dhcp_state = NULL;
2210 u8_t hwaddr_len;
2211 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_release()\n"));
2212 LWIP_ERROR("netif != NULL", (netif != NULL), return ERR_ARG);
2213 netif_dhcp = netif_dhcp_data(netif);
2214 if (netif_dhcp == NULL) {
2215 return ERR_ARG;
2216 }
2217
2218 netif_dhcp->client.cli_idx = LWIP_DHCP_NATIVE_IDX;
2219 dhcp_state = &((netif_dhcp->client.states)[LWIP_DHCP_NATIVE_IDX]);
2220 if (dhcp_state->state == DHCP_STATE_OFF) {
2221 return ERR_ARG;
2222 }
2223
2224 if (dhcp_idx_to_mac(netif, LWIP_DHCP_NATIVE_IDX, netif_dhcp->client.hwaddr, &hwaddr_len) != ERR_OK) {
2225 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_release():get mac failed\n"));
2226 return ERR_VAL;
2227 }
2228 dhcp_state->hwaddr_len = hwaddr_len;
2229
2230 #if LWIP_DHCP_BOOTP_FILE
2231 ip4_addr_set_zero(&netif_dhcp->offered_si_addr);
2232 #endif /* LWIP_DHCP_BOOTP_FILE */
2233
2234 result = dhcp_release_client(netif, &(netif_dhcp->client));
2235
2236 /* remove IP address from interface (prevents routing from selecting this interface) */
2237 (void)netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4);
2238
2239 return result;
2240 }
2241
2242 static void
dhcp_stop_client(struct netif * netif,struct dhcp_client * dhcp)2243 dhcp_stop_client(struct netif *netif, struct dhcp_client *dhcp)
2244 {
2245 struct dhcp *netif_dhcp = NULL;
2246 struct dhcp_state *dhcp_state = &((dhcp->states)[dhcp->cli_idx]);
2247
2248 netif_dhcp = netif_dhcp_data(netif);
2249
2250 LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL);
2251 #if (LWIP_DHCP_SUBSTITUTE && LWIP_DHCP_LIMIT_CONCURRENT_REQUESTS)
2252 dhcp_concurrent_stop_client(dhcp);
2253 #endif
2254 if (dhcp->cli_idx == LWIP_DHCP_NATIVE_IDX) {
2255 (void)dhcp_release(netif);
2256 if (netif_dhcp->pcb_allocated != 0) {
2257 dhcp_dec_pcb_refcount(); /* free DHCP PCB if not needed any more */
2258 netif_dhcp->pcb_allocated = 0;
2259 }
2260 } else {
2261 #if LWIP_DHCP_SUBSTITUTE
2262 (void)dhcp_release_client(netif, dhcp);
2263 dhcp_dec_pcb_refcount();
2264 #endif /* LWIP_DHCP_SUBSTITUTE */
2265 }
2266 dhcp_set_state(dhcp, DHCP_STATE_OFF);
2267 (void)memset_s(dhcp_state, sizeof(struct dhcp_state), 0, sizeof(struct dhcp_state));
2268 dhcp_clients_count_update(dhcp);
2269 }
2270
2271 /**
2272 * @ingroup dhcp4
2273 * Remove the DHCP client from the interface.
2274 *
2275 * @param netif The network interface to stop DHCP on
2276 */
2277 void
dhcp_stop(struct netif * netif)2278 dhcp_stop(struct netif *netif)
2279 {
2280 struct dhcp *netif_dhcp = NULL;
2281 struct dhcp_state *dhcp_state = NULL;
2282 u8_t hwaddr_len;
2283 LWIP_ERROR("dhcp_stop: netif != NULL", (netif != NULL), return);
2284 netif_dhcp = netif_dhcp_data(netif);
2285 netif->flags = netif->flags & (~NETIF_FLAG_DHCP);
2286 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_stop()\n"));
2287 if (netif_dhcp != NULL) {
2288 #if LWIP_DHCP_AUTOIP_COOP
2289 if (netif_dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) {
2290 autoip_stop(netif);
2291 netif_dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF;
2292 }
2293 #endif /* LWIP_DHCP_AUTOIP_COOP */
2294 netif_dhcp->client.cli_idx = LWIP_DHCP_NATIVE_IDX;
2295 dhcp_state = &((netif_dhcp->client.states)[LWIP_DHCP_NATIVE_IDX]);
2296 if (dhcp_idx_to_mac(netif, LWIP_DHCP_NATIVE_IDX, netif_dhcp->client.hwaddr, &hwaddr_len) != ERR_OK) {
2297 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_stop():get mac failed\n"));
2298 return;
2299 }
2300 dhcp_state->hwaddr_len = hwaddr_len;
2301 dhcp_stop_client(netif, &(netif_dhcp->client));
2302 }
2303 }
2304
2305 /*
2306 * Set the DHCP state of a DHCP client.
2307 *
2308 * If the state changed, reset the number of tries.
2309 */
2310 static void
dhcp_set_state(struct dhcp_client * dhcp,u8_t new_state)2311 dhcp_set_state(struct dhcp_client *dhcp, u8_t new_state)
2312 {
2313 struct dhcp_state *dhcp_state = &((dhcp->states)[dhcp->cli_idx]);
2314 if (new_state != dhcp_state->state) {
2315 LWIP_DEBUGF_LOG2(DHCP_DEBUG | LWIP_DBG_TRACE, "dhcp_set_state:%hhu to %hhu\n", dhcp_state->state, new_state);
2316 dhcp_state->state = new_state;
2317 dhcp_state->tries = 0;
2318 dhcp_state->request_timeout = 0;
2319 }
2320 }
2321
2322 /*
2323 * Concatenate an option type and length field to the outgoing
2324 * DHCP message.
2325 *
2326 */
2327 static u16_t
dhcp_option(u16_t options_out_len,u8_t * options,u8_t option_type,u8_t option_len)2328 dhcp_option(u16_t options_out_len, u8_t *options, u8_t option_type, u8_t option_len)
2329 {
2330 LWIP_ASSERT("dhcp_option: options_out_len + 2 + option_len <= DHCP_OPTIONS_LEN", options_out_len + 2U + option_len <= DHCP_OPTIONS_LEN);
2331 options[options_out_len++] = option_type;
2332 options[options_out_len++] = option_len;
2333 return options_out_len;
2334 }
2335 /*
2336 * Concatenate a single byte to the outgoing DHCP message.
2337 *
2338 */
2339 static u16_t
dhcp_option_byte(u16_t options_out_len,u8_t * options,u8_t value)2340 dhcp_option_byte(u16_t options_out_len, u8_t *options, u8_t value)
2341 {
2342 LWIP_ASSERT("dhcp_option_byte: options_out_len < DHCP_OPTIONS_LEN", options_out_len < DHCP_OPTIONS_LEN);
2343 options[options_out_len++] = value;
2344 return options_out_len;
2345 }
2346
2347 static u16_t
dhcp_option_short(u16_t options_out_len,u8_t * options,u16_t value)2348 dhcp_option_short(u16_t options_out_len, u8_t *options, u16_t value)
2349 {
2350 LWIP_ASSERT("dhcp_option_short: options_out_len + 2 <= DHCP_OPTIONS_LEN", options_out_len + 2U <= DHCP_OPTIONS_LEN);
2351 options[options_out_len++] = (u8_t)((value & 0xff00U) >> 8);
2352 options[options_out_len++] = (u8_t) (value & 0x00ffU);
2353 return options_out_len;
2354 }
2355
2356 static u16_t
dhcp_option_long(u16_t options_out_len,u8_t * options,u32_t value)2357 dhcp_option_long(u16_t options_out_len, u8_t *options, u32_t value)
2358 {
2359 LWIP_ASSERT("dhcp_option_long: options_out_len + 4 <= DHCP_OPTIONS_LEN", options_out_len + 4U <= DHCP_OPTIONS_LEN);
2360 options[options_out_len++] = (u8_t)((value & 0xff000000UL) >> 24);
2361 options[options_out_len++] = (u8_t)((value & 0x00ff0000UL) >> 16);
2362 options[options_out_len++] = (u8_t)((value & 0x0000ff00UL) >> 8);
2363 options[options_out_len++] = (u8_t)((value & 0x000000ffUL));
2364 return options_out_len;
2365 }
2366
2367 #if LWIP_NETIF_HOSTNAME
2368 static u16_t
dhcp_option_hostname(u16_t options_out_len,u8_t * options,struct netif * netif)2369 dhcp_option_hostname(u16_t options_out_len, u8_t *options, struct netif *netif)
2370 {
2371 const char *p = NULL;
2372 char dhcp_hostname[NETIF_HOSTNAME_MAX_LEN];
2373 size_t namelen = strlen(netif->hostname);
2374 if (namelen > 0) {
2375 p = netif->hostname;
2376 }
2377
2378 if (p == NULL) {
2379 if (snprintf_s(dhcp_hostname, NETIF_HOSTNAME_MAX_LEN,
2380 NETIF_HOSTNAME_MAX_LEN - 1, "%02x%02x%02x%02x%02x%02x",
2381 netif->hwaddr[0], netif->hwaddr[1], netif->hwaddr[2],
2382 netif->hwaddr[3], netif->hwaddr[4], netif->hwaddr[5]) <= 0) {
2383 return options_out_len;
2384 }
2385 dhcp_hostname[NETIF_HOSTNAME_MAX_LEN - 1] = '\0';
2386 p = dhcp_hostname;
2387 }
2388
2389 namelen = strlen(p);
2390 /* Validate length against available bytes (need 2 bytes for OPTION_HOSTNAME
2391 and 1 byte for trailer) */
2392 LWIP_ASSERT("DHCP: hostname is too long!", namelen + 3 + options_out_len <= DHCP_OPTIONS_LEN);
2393 options_out_len = dhcp_option(options_out_len, options, DHCP_OPTION_HOSTNAME, (u8_t)namelen);
2394 while (namelen--) {
2395 options_out_len = dhcp_option_byte(options_out_len, options, (u8_t)(*p++));
2396 }
2397
2398 return options_out_len;
2399 }
2400 #endif /* LWIP_NETIF_HOSTNAME */
2401
2402 #if LWIP_DHCP_VENDOR_CLASS_IDENTIFIER
2403 static u16_t
dhcp_option_vci(u16_t options_out_len,u8_t * options,const struct netif * netif)2404 dhcp_option_vci(u16_t options_out_len, u8_t *options, const struct netif *netif)
2405 {
2406 const char *p = NULL;
2407 u8_t len;
2408 size_t vci_len;
2409 size_t available;
2410
2411 LWIP_UNUSED_ARG(netif);
2412
2413 vci_len = g_vci_info.vci_len;
2414 if (vci_len > 0) {
2415 p = g_vci_info.vci;
2416 } else {
2417 return options_out_len;
2418 }
2419
2420 /* Shrink len to available bytes (need 2 bytes for DHCP_OPTION_VCI
2421 and 1 byte for trailer) */
2422 available = DHCP_OPTIONS_LEN - options_out_len - 3;
2423 LWIP_ASSERT("DHCP: vci is too long!", vci_len <= available);
2424 len = (u8_t)LWIP_MIN(vci_len, available);
2425 options_out_len = dhcp_option(options_out_len, options, DHCP_OPTION_VCI, (u8_t)len);
2426 while (len--) {
2427 options_out_len = dhcp_option_byte(options_out_len, options, *p++);
2428 }
2429 return options_out_len;
2430 }
2431
2432 err_t
dhcp_set_vci(const char * vci,u8_t vci_len)2433 dhcp_set_vci(const char *vci, u8_t vci_len)
2434 {
2435 if (memcpy_s(g_vci_info.vci, DHCP_VCI_MAX_LEN, vci, vci_len) == EOK) {
2436 g_vci_info.vci_len = vci_len;
2437 return ERR_OK;
2438 }
2439 return ERR_MEM;
2440 }
2441
2442 err_t
dhcp_get_vci(char * vci,u8_t * vci_len)2443 dhcp_get_vci(char *vci, u8_t *vci_len)
2444 {
2445 if (g_vci_info.vci_len == 0) {
2446 *vci_len = 0;
2447 return ERR_VAL;
2448 } else {
2449 if (memcpy_s(vci, *vci_len, g_vci_info.vci, g_vci_info.vci_len) == EOK) {
2450 *vci_len = g_vci_info.vci_len;
2451 return ERR_OK;
2452 } else {
2453 *vci_len = 0;
2454 return ERR_VAL;
2455 }
2456 }
2457 }
2458 #endif /* LWIP_DHCP_VENDOR_CLASS_IDENTIFIER */
2459
2460 /**
2461 * Extract the DHCP message and the DHCP options.
2462 *
2463 * Extract the DHCP message and the DHCP options, each into a contiguous
2464 * piece of memory. As a DHCP message is variable sized by its options,
2465 * and also allows overriding some fields for options, the easy approach
2466 * is to first unfold the options into a contiguous piece of memory, and
2467 * use that further on.
2468 *
2469 */
2470 static err_t
dhcp_parse_reply(struct dhcp * netif_dhcp,struct dhcp_client * dhcp,struct pbuf * p)2471 dhcp_parse_reply(struct dhcp *netif_dhcp, struct dhcp_client *dhcp, struct pbuf *p)
2472 {
2473 u8_t *options = NULL;
2474 u16_t offset;
2475 u16_t offset_max;
2476 u16_t options_offset;
2477 u16_t options_idx;
2478 u16_t options_idx_max;
2479 struct pbuf *q = NULL;
2480 int parse_file_as_options = 0;
2481 int parse_sname_as_options = 0;
2482 #if LWIP_DHCP_BOOTP_FILE
2483 int file_overloaded = 0;
2484 #endif
2485 (void)netif_dhcp;
2486
2487 /* clear received options */
2488 dhcp_clear_all_options(dhcp);
2489 /* check that beginning of dhcp_msg (up to and including chaddr) is in first pbuf */
2490 if (p->len < DHCP_SNAME_OFS) {
2491 return ERR_BUF;
2492 }
2493 dhcp->msg_in = (struct dhcp_msg *)p->payload;
2494 #if LWIP_DHCP_BOOTP_FILE
2495 /* clear boot file name */
2496 if (dhcp->cli_idx == LWIP_DHCP_NATIVE_IDX) {
2497 netif_dhcp->boot_file_name[0] = 0;
2498 }
2499 #endif /* LWIP_DHCP_BOOTP_FILE */
2500
2501 /* parse options */
2502
2503 /* start with options field */
2504 options_idx = DHCP_OPTIONS_OFS;
2505 /* parse options to the end of the received packet */
2506 options_idx_max = p->tot_len;
2507 again:
2508 q = p;
2509 options_offset = options_idx;
2510 while ((q != NULL) && (options_idx >= q->len)) {
2511 options_idx = (u16_t)(options_idx - q->len);
2512 options_idx_max = (u16_t)(options_idx_max - q->len);
2513 q = q->next;
2514 }
2515 if (q == NULL) {
2516 return ERR_BUF;
2517 }
2518 offset = options_idx;
2519 offset_max = options_idx_max;
2520 options = (u8_t *)q->payload;
2521 /* at least 1 byte to read and no end marker, then at least 3 bytes to read? */
2522 while ((q != NULL) && (offset < offset_max) && (options[offset] != DHCP_OPTION_END)) {
2523 u8_t op = options[offset];
2524 u8_t len;
2525 u8_t decode_len = 0;
2526 int decode_idx = 0;
2527 u16_t val_offset = (u16_t)(offset + 2);
2528 if (val_offset < offset) {
2529 /* overflow */
2530 return ERR_BUF;
2531 }
2532 /* len byte might be in the next pbuf */
2533 if ((offset + 1) < q->len) {
2534 len = options[offset + 1];
2535 } else {
2536 len = (q->next != NULL ? ((u8_t *)q->next->payload)[0] : 0);
2537 }
2538 /* LWIP_DEBUGF(DHCP_DEBUG, ("msg_offset=%"U16_F", q->len=%"U16_F, msg_offset, q->len)); */
2539 decode_len = len;
2540 switch (op) {
2541 /* case(DHCP_OPTION_END): handled above */
2542 case (DHCP_OPTION_PAD):
2543 /* special option: no len encoded */
2544 decode_len = len = 0;
2545 /* will be increased below */
2546 break;
2547 case (DHCP_OPTION_SUBNET_MASK):
2548 LWIP_DHCP_INPUT_ERROR("len == 4", len == 4, return ERR_VAL;);
2549 decode_idx = DHCP_OPTION_IDX_SUBNET_MASK;
2550 break;
2551 case (DHCP_OPTION_ROUTER):
2552 decode_len = 4; /* only copy the first given router */
2553 LWIP_DHCP_INPUT_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;);
2554 decode_idx = DHCP_OPTION_IDX_ROUTER;
2555 break;
2556 #if LWIP_DHCP_PROVIDE_DNS_SERVERS
2557 case (DHCP_OPTION_DNS_SERVER):
2558 /* special case: there might be more than one server */
2559 LWIP_DHCP_INPUT_ERROR("len %% 4 == 0", len % 4 == 0, return ERR_VAL;);
2560 /* limit number of DNS servers */
2561 #if DNS_MAX_SERVERS > 64
2562 #error "Max number of servers can not be greater than 64"
2563 #endif
2564 decode_len = LWIP_MIN(len, 4 * DNS_MAX_SERVERS);
2565 LWIP_DHCP_INPUT_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;);
2566 decode_idx = DHCP_OPTION_IDX_DNS_SERVER;
2567 break;
2568 #endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS */
2569 case (DHCP_OPTION_LEASE_TIME):
2570 LWIP_DHCP_INPUT_ERROR("len == 4", len == 4, return ERR_VAL;);
2571 decode_idx = DHCP_OPTION_IDX_LEASE_TIME;
2572 break;
2573 #if LWIP_DHCP_GET_NTP_SRV
2574 case (DHCP_OPTION_NTP):
2575 /* special case: there might be more than one server */
2576 LWIP_DHCP_INPUT_ERROR("len %% 4 == 0", len % 4 == 0, return ERR_VAL;);
2577 /* limit number of NTP servers */
2578 decode_len = LWIP_MIN(len, 4 * LWIP_DHCP_MAX_NTP_SERVERS);
2579 LWIP_DHCP_INPUT_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;);
2580 decode_idx = DHCP_OPTION_IDX_NTP_SERVER;
2581 break;
2582 #endif /* LWIP_DHCP_GET_NTP_SRV*/
2583 case (DHCP_OPTION_OVERLOAD):
2584 LWIP_DHCP_INPUT_ERROR("len == 1", len == 1, return ERR_VAL;);
2585 /* decode overload only in options, not in file/sname: invalid packet */
2586 LWIP_DHCP_INPUT_ERROR("overload in file/sname", options_offset == DHCP_OPTIONS_OFS, return ERR_VAL;);
2587 decode_idx = DHCP_OPTION_IDX_OVERLOAD;
2588 break;
2589 case (DHCP_OPTION_MESSAGE_TYPE):
2590 LWIP_DHCP_INPUT_ERROR("len == 1", len == 1, return ERR_VAL;);
2591 decode_idx = DHCP_OPTION_IDX_MSG_TYPE;
2592 break;
2593 case (DHCP_OPTION_SERVER_ID):
2594 LWIP_DHCP_INPUT_ERROR("len == 4", len == 4, return ERR_VAL;);
2595 decode_idx = DHCP_OPTION_IDX_SERVER_ID;
2596 break;
2597 case (DHCP_OPTION_T1):
2598 LWIP_DHCP_INPUT_ERROR("len == 4", len == 4, return ERR_VAL;);
2599 decode_idx = DHCP_OPTION_IDX_T1;
2600 break;
2601 case (DHCP_OPTION_T2):
2602 LWIP_DHCP_INPUT_ERROR("len == 4", len == 4, return ERR_VAL;);
2603 decode_idx = DHCP_OPTION_IDX_T2;
2604 break;
2605 default:
2606 decode_len = 0;
2607 LWIP_DEBUGF_LOG1(DHCP_DEBUG, "skipping option %"U16_F" in options\n", (u16_t)op);
2608 LWIP_HOOK_DHCP_PARSE_OPTION(ip_current_netif(), dhcp, dhcp->state, dhcp->msg_in,
2609 dhcp_option_given(dhcp, DHCP_OPTION_IDX_MSG_TYPE) ? (u8_t)dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_MSG_TYPE) : 0,
2610 op, len, q, val_offset);
2611 break;
2612 }
2613 if (op == DHCP_OPTION_PAD) {
2614 offset++;
2615 } else {
2616 if (offset + len + 2 > 0xFFFF) {
2617 /* overflow */
2618 return ERR_BUF;
2619 }
2620 offset = (u16_t)(offset + len + 2);
2621 if (decode_len > 0) {
2622 u32_t value = 0;
2623 u16_t copy_len;
2624 decode_next:
2625 LWIP_ASSERT("check decode_idx", decode_idx >= 0 && decode_idx < DHCP_OPTION_IDX_MAX);
2626 if (!dhcp_option_given(dhcp, decode_idx)) {
2627 copy_len = LWIP_MIN(decode_len, 4);
2628 if (pbuf_copy_partial(q, &value, copy_len, val_offset) != copy_len) {
2629 return ERR_BUF;
2630 }
2631 if (decode_len > 4) {
2632 /* decode more than one u32_t */
2633 u16_t next_val_offset;
2634 LWIP_DHCP_INPUT_ERROR("decode_len %% 4 == 0", decode_len % 4 == 0, return ERR_VAL;);
2635 dhcp_got_option(dhcp, decode_idx);
2636 dhcp_set_option_value(dhcp, decode_idx, lwip_htonl(value));
2637 decode_len = (u8_t)(decode_len - 4);
2638 next_val_offset = (u16_t)(val_offset + 4);
2639 if (next_val_offset < val_offset) {
2640 /* overflow */
2641 return ERR_BUF;
2642 }
2643 val_offset = next_val_offset;
2644 decode_idx++;
2645 goto decode_next;
2646 } else if (decode_len == 4) {
2647 value = lwip_ntohl(value);
2648 } else {
2649 LWIP_DHCP_INPUT_ERROR("invalid decode_len", decode_len == 1, return ERR_VAL;);
2650 value = ((u8_t *)&value)[0];
2651 }
2652 dhcp_got_option(dhcp, decode_idx);
2653 dhcp_set_option_value(dhcp, decode_idx, value);
2654 }
2655 }
2656 }
2657 if (offset >= q->len) {
2658 offset = (u16_t)(offset - q->len);
2659 offset_max = (u16_t)(offset_max - q->len);
2660 if (offset < offset_max) {
2661 q = q->next;
2662 LWIP_DHCP_INPUT_ERROR("next pbuf was null", q != NULL, return ERR_VAL;);
2663 options = (u8_t *)q->payload;
2664 } else {
2665 /* We've run out of bytes, probably no end marker. Don't proceed. */
2666 return ERR_BUF;
2667 }
2668 }
2669 }
2670 /* is this an overloaded message? */
2671 if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_OVERLOAD)) {
2672 u32_t overload = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_OVERLOAD);
2673 dhcp_clear_option(dhcp, DHCP_OPTION_IDX_OVERLOAD);
2674 if (overload == DHCP_OVERLOAD_FILE) {
2675 parse_file_as_options = 1;
2676 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded file field\n"));
2677 } else if (overload == DHCP_OVERLOAD_SNAME) {
2678 parse_sname_as_options = 1;
2679 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded sname field\n"));
2680 } else if (overload == DHCP_OVERLOAD_SNAME_FILE) {
2681 parse_sname_as_options = 1;
2682 parse_file_as_options = 1;
2683 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded sname and file field\n"));
2684 } else {
2685 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("invalid overload option: %d\n", (int)overload));
2686 }
2687 }
2688 if (parse_file_as_options) {
2689 /* if both are overloaded, parse file first and then sname (RFC 2131 ch. 4.1) */
2690 parse_file_as_options = 0;
2691 options_idx = DHCP_FILE_OFS;
2692 options_idx_max = DHCP_FILE_OFS + DHCP_FILE_LEN;
2693 #if LWIP_DHCP_BOOTP_FILE
2694 file_overloaded = 1;
2695 #endif
2696 goto again;
2697 } else if (parse_sname_as_options) {
2698 parse_sname_as_options = 0;
2699 options_idx = DHCP_SNAME_OFS;
2700 options_idx_max = DHCP_SNAME_OFS + DHCP_SNAME_LEN;
2701 goto again;
2702 }
2703 #if LWIP_DHCP_BOOTP_FILE
2704 if (!file_overloaded) {
2705 /* only do this for ACK messages */
2706 if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_MSG_TYPE) &&
2707 (dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_MSG_TYPE) == DHCP_ACK)) {
2708 /* copy bootp file name, don't care for sname (server hostname) */
2709 if (pbuf_copy_partial(p, netif_dhcp->boot_file_name, DHCP_FILE_LEN - 1, DHCP_FILE_OFS) != (DHCP_FILE_LEN - 1)) {
2710 return ERR_BUF;
2711 }
2712 }
2713 /* make sure the string is really NULL-terminated */
2714 netif_dhcp->boot_file_name[DHCP_FILE_LEN - 1] = 0;
2715 }
2716 #endif /* LWIP_DHCP_BOOTP_FILE */
2717 return ERR_OK;
2718 }
2719
2720 /**
2721 * If an incoming DHCP message is in response to us, then trigger the state machine
2722 */
2723 static void
dhcp_recv(void * arg,struct udp_pcb * pcb,struct pbuf * p,const ip_addr_t * addr,u16_t port)2724 dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
2725 {
2726 struct netif *netif = ip_current_input_netif();
2727 struct dhcp *netif_dhcp = netif_dhcp_data(netif);
2728 struct dhcp_client *dhcp = NULL;
2729 struct dhcp_msg *reply_msg = (struct dhcp_msg *)p->payload;
2730 u8_t msg_type;
2731 dhcp_num_t mac_idx;
2732 struct dhcp_state *dhcp_state = NULL;
2733 u8_t hwaddr_len;
2734 u32_t xid;
2735 #if LWIP_DHCP_SUBSTITUTE
2736 ip_addr_t server_id;
2737 #endif /* LWIP_DHCP_SUBSTITUTE */
2738
2739 LWIP_UNUSED_ARG(arg);
2740
2741 /* Caught DHCP message from netif that does not have DHCP enabled? -> not interested */
2742 if ((netif_dhcp == NULL) || (dhcp_pcb_refcount == 0)) {
2743 goto free_pbuf_and_return;
2744 }
2745
2746 LWIP_ASSERT("invalid server address type", IP_IS_V4(addr));
2747
2748 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,
2749 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));
2750 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("pbuf->len = %"U16_F"\n", p->len));
2751 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("pbuf->tot_len = %"U16_F"\n", p->tot_len));
2752 /* prevent warnings about unused arguments */
2753 LWIP_UNUSED_ARG(pcb);
2754 LWIP_UNUSED_ARG(addr);
2755 LWIP_UNUSED_ARG(port);
2756
2757 if (p->len < DHCP_MIN_REPLY_LEN) {
2758 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("DHCP reply message or pbuf too short\n"));
2759 goto free_pbuf_and_return;
2760 }
2761
2762 if (reply_msg->op != DHCP_BOOTREPLY) {
2763 LWIP_DEBUGF_LOG1(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
2764 "not a DHCP reply message, but type %"U16_F"\n", (u16_t)reply_msg->op);
2765 goto free_pbuf_and_return;
2766 }
2767
2768 dhcp = &(netif_dhcp->client);
2769
2770 if (dhcp_mac_to_idx(netif, reply_msg->chaddr, reply_msg->hlen, &mac_idx) != ERR_OK) {
2771 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_recv(): mac idx failed\n"));
2772 goto free_pbuf_and_return;
2773 }
2774 if (dhcp_client_find_by_mac_idx(dhcp, mac_idx, &(dhcp->cli_idx)) != ERR_OK) {
2775 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_recv(): no client\n"));
2776 goto free_pbuf_and_return;
2777 }
2778 dhcp_state = &((dhcp->states)[dhcp->cli_idx]);
2779 if (dhcp_idx_to_mac(netif, dhcp_state->idx, dhcp->hwaddr, &hwaddr_len) != ERR_OK) {
2780 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_recv(): get mac failed\n"));
2781 goto free_pbuf_and_return;
2782 }
2783 dhcp_state->hwaddr_len = hwaddr_len;
2784
2785 LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL);
2786
2787 /* match transaction ID against what we expected */
2788 DHCP_XID(xid, dhcp->hwaddr, dhcp_state->hwaddr_len, dhcp_state->xid);
2789 if (lwip_ntohl(reply_msg->xid) != xid) {
2790 LWIP_DEBUGF_LOG2(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
2791 "transaction id mismatch reply_msg->xid(%"X32_F")!=dhcp->xid(%"X32_F")\n",
2792 lwip_ntohl(reply_msg->xid), xid);
2793 goto free_pbuf_and_return;
2794 }
2795 /* option fields could be unfold? */
2796 if (dhcp_parse_reply(netif_dhcp, dhcp, p) != ERR_OK) {
2797 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
2798 ("problem unfolding DHCP message - too short on memory?\n"));
2799 goto free_pbuf_and_return;
2800 }
2801
2802 #if LWIP_DHCP_SUBSTITUTE
2803 /* to check if the server changed */
2804 if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_SERVER_ID)) {
2805 ip_addr_set_ip4_u32_val(server_id, lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_SERVER_ID)));
2806 if (!(ip4_addr_isany_val(dhcp->server_ip_addr.u_addr.ip4)) &&
2807 !(ip4_addr_cmp(ip_2_ip4(&server_id), ip_2_ip4(&(dhcp->server_ip_addr))))) {
2808 LWIP_DEBUGF_LOG2(DHCP_DEBUG | LWIP_DBG_TRACE,
2809 "%u diff serv_id %u\n", dhcp->cli_idx, ip_2_ip4(&server_id)->addr);
2810 if (dhcp->cli_idx != LWIP_DHCP_NATIVE_IDX) {
2811 goto free_pbuf_and_return;
2812 }
2813 dhcp_substitute_clients_restart(netif, dhcp);
2814 dhcp->cli_idx = LWIP_DHCP_NATIVE_IDX;
2815 if (dhcp_idx_to_mac(netif, dhcp_state->idx, dhcp->hwaddr, &hwaddr_len) != ERR_OK) {
2816 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_recv(): get mac failed\n"));
2817 goto free_pbuf_and_return;
2818 }
2819 dhcp_state->hwaddr_len = hwaddr_len;
2820 }
2821 } else {
2822 LWIP_DEBUGF_LOG1(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
2823 "dhcp_recv(netif=%p) did not get server ID!\n", (void *)netif);
2824 goto free_pbuf_and_return;
2825 }
2826 #endif /* LWIP_DHCP_SUBSTITUTE */
2827 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE, ("searching DHCP_OPTION_MESSAGE_TYPE\n"));
2828 /* obtain pointer to DHCP message type */
2829 if (!dhcp_option_given(dhcp, DHCP_OPTION_IDX_MSG_TYPE)) {
2830 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
2831 ("DHCP_OPTION_MESSAGE_TYPE option not found\n"));
2832 goto free_pbuf_and_return;
2833 }
2834
2835 /* read DHCP message type */
2836 msg_type = (u8_t)dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_MSG_TYPE);
2837 /* message type is DHCP ACK? */
2838 if (msg_type == DHCP_ACK) {
2839 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_ACK received\n"));
2840 /* in requesting state or just reconnected to the network? */
2841 if ((dhcp_state->state == DHCP_STATE_REQUESTING) ||
2842 (dhcp_state->state == DHCP_STATE_REBOOTING)) {
2843 dhcp_handle_ack(netif, dhcp);
2844 #if LWIP_DHCP_SUBSTITUTE
2845 ip4_addr_t cli_ip;
2846 dhcp_get_client_ip(&cli_ip.addr, dhcp, dhcp_state);
2847 if (dhcp_addr_clients_check(netif_dhcp, &cli_ip) == lwIP_TRUE) {
2848 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
2849 ("addr been used by substitute client\n"));
2850 (void)dhcp_decline(netif, dhcp);
2851 goto free_pbuf_and_return;
2852 }
2853 #endif /* LWIP_DHCP_SUBSTITUTE */
2854 #if DHCP_DOES_ARP_CHECK
2855 if (
2856 #if LWIP_DHCP_SUBSTITUTE_MMBR
2857 (dhcp_state->addr_not_dup_check == lwIP_FALSE) &&
2858 #endif
2859 ((netif->flags & NETIF_FLAG_ETHARP) != 0)) {
2860 /* check if the acknowledged lease address is already in use */
2861 dhcp_check(netif, dhcp);
2862 } else {
2863 /* bind interface to the acknowledged lease address */
2864 dhcp_bind(netif, dhcp);
2865 }
2866 #else
2867 /* bind interface to the acknowledged lease address */
2868 dhcp_bind(netif, dhcp);
2869 #endif
2870 #if LWIP_DHCP_SUBSTITUTE_MMBR
2871 dhcp_state->addr_not_dup_check = lwIP_FALSE;
2872 #endif /* LWIP_DHCP_SUBSTITUTE_MMBR */
2873 }
2874 /* already bound to the given lease address? */
2875 else if ((dhcp_state->state == DHCP_STATE_REBINDING) ||
2876 (dhcp_state->state == DHCP_STATE_RENEWING)) {
2877 dhcp_handle_ack(netif, dhcp);
2878 dhcp_bind(netif, dhcp);
2879 }
2880 }
2881 /* received a DHCP_NAK in appropriate state? */
2882 else if ((msg_type == DHCP_NAK) &&
2883 ((dhcp_state->state == DHCP_STATE_REBOOTING) || (dhcp_state->state == DHCP_STATE_REQUESTING) ||
2884 (dhcp_state->state == DHCP_STATE_REBINDING) || (dhcp_state->state == DHCP_STATE_RENEWING))) {
2885 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_NAK received\n"));
2886 #if LWIP_DHCP_SUBSTITUTE_MMBR
2887 /* ignore the preferred IP if receive NAK */
2888 dhcp_state->addr_not_dup_check = lwIP_FALSE;
2889 #endif /* LWIP_DHCP_SUBSTITUTE_MMBR */
2890 dhcp_handle_nak(netif, dhcp);
2891 }
2892 /* received a DHCP_OFFER in DHCP_STATE_SELECTING state? */
2893 else if ((msg_type == DHCP_OFFER) && (dhcp_state->state == DHCP_STATE_SELECTING)) {
2894 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_OFFER received in DHCP_STATE_SELECTING state\n"));
2895 /* remember offered lease */
2896 dhcp_handle_offer(netif, dhcp);
2897 }
2898
2899 free_pbuf_and_return:
2900 if (dhcp != NULL) {
2901 dhcp->msg_in = NULL;
2902 }
2903 pbuf_free(p);
2904 }
2905
2906 /**
2907 * Create a DHCP request, fill in common headers
2908 *
2909 * @param netif the netif under DHCP control
2910 * @param dhcp dhcp control struct
2911 * @param message_type message type of the request
2912 */
2913 static err_t
dhcp_create_msg(struct netif * netif,struct dhcp_client * dhcp,u8_t message_type,u16_t * options_out_len)2914 dhcp_create_msg(struct netif *netif, struct dhcp_client *dhcp, u8_t message_type, u16_t *options_out_len)
2915 {
2916 u16_t i;
2917 ip4_addr_t cli_ip;
2918 u16_t options_out_len_loc;
2919 struct dhcp_state *dhcp_state = NULL;
2920
2921 #ifndef DHCP_GLOBAL_XID
2922 /** default global transaction identifier starting value (easy to match
2923 * with a packet analyser). We simply increment for each new request.
2924 * Predefine DHCP_GLOBAL_XID to a better value or a function call to generate one
2925 * at runtime, any supporting function prototypes can be defined in DHCP_GLOBAL_XID_HEADER */
2926 #if DHCP_CREATE_RAND_XID && defined(LWIP_RAND)
2927 static u32_t xid;
2928 #else /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */
2929 static u32_t xid = 0xABCD0000;
2930 #endif /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */
2931 #else
2932 if (!xid_initialised) {
2933 xid = DHCP_GLOBAL_XID;
2934 xid_initialised = !xid_initialised;
2935 }
2936 #endif
2937 LWIP_ERROR("dhcp_create_msg: netif != NULL", (netif != NULL), return ERR_ARG);
2938 LWIP_ERROR("dhcp_create_msg: dhcp != NULL", (dhcp != NULL), return ERR_VAL);
2939 LWIP_ASSERT("dhcp_create_msg: dhcp->p_out == NULL", dhcp->p_out == NULL);
2940 LWIP_ASSERT("dhcp_create_msg: dhcp->msg_out == NULL", dhcp->msg_out == NULL);
2941 dhcp_state = &((dhcp->states)[dhcp->cli_idx]);
2942 dhcp->p_out = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcp_msg), PBUF_RAM);
2943 if (dhcp->p_out == NULL) {
2944 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
2945 ("dhcp_create_msg(): could not allocate pbuf\n"));
2946 return ERR_MEM;
2947 }
2948 LWIP_ASSERT("dhcp_create_msg: check that first pbuf can hold struct dhcp_msg",
2949 (dhcp->p_out->len >= sizeof(struct dhcp_msg)));
2950
2951 #if DRIVER_STATUS_CHECK
2952 dhcp->p_out->flags |= PBUF_FLAG_DHCP_BUF;
2953 #endif
2954
2955 /* DHCP_REQUEST should reuse 'xid' from DHCPOFFER */
2956 if ((message_type != DHCP_REQUEST) || (dhcp_state->state == DHCP_STATE_REBOOTING)) {
2957 /* reuse transaction identifier in retransmissions */
2958 if (dhcp_state->tries == 0) {
2959 #if DHCP_CREATE_RAND_XID && defined(LWIP_RAND)
2960 xid = (u32_t)LWIP_RAND();
2961 #else /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */
2962 xid++;
2963 #endif /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */
2964 dhcp_state->xid = (u8_t)xid;
2965 }
2966 }
2967 LWIP_DEBUGF_LOG1(DHCP_DEBUG | LWIP_DBG_TRACE,
2968 "transaction id xid(%"X32_F")\n", xid);
2969
2970 dhcp->msg_out = (struct dhcp_msg *)dhcp->p_out->payload;
2971 memset(dhcp->msg_out, 0, sizeof(struct dhcp_msg));
2972
2973 dhcp->msg_out->op = DHCP_BOOTREQUEST;
2974 #if LWIP_ALWAYS_SEND_HWTYPE_AS_ETHER_IN_DHCP
2975 dhcp->msg_out->htype = LWIP_IANA_HWTYPE_ETHERNET;
2976 #else
2977 dhcp->msg_out->htype = (u8_t)(netif->link_layer_type & 0xFF);
2978 #endif
2979 dhcp->msg_out->hlen = dhcp_state->hwaddr_len;
2980 dhcp->msg_out->hops = 0;
2981 DHCP_XID(dhcp->msg_out->xid, dhcp->hwaddr, dhcp_state->hwaddr_len, dhcp_state->xid);
2982 dhcp->msg_out->xid = lwip_htonl(dhcp->msg_out->xid);
2983 dhcp->msg_out->secs = 0;
2984 /* we don't need the broadcast flag since we can receive unicast traffic
2985 before being fully configured! */
2986 dhcp->msg_out->flags = 0;
2987 #if LWIP_DHCP_SUBSTITUTE
2988 if (dhcp->cli_idx != LWIP_DHCP_NATIVE_IDX) {
2989 dhcp->msg_out->flags |= lwip_htons(DHCP_BROADCAST_FLAG);
2990 }
2991 #endif /* LWIP_DHCP_SUBSTITUTE */
2992 ip4_addr_set_zero(&dhcp->msg_out->ciaddr);
2993 /* set ciaddr to dhcp->offered_ip_addr based on message_type and state */
2994 if (message_type == DHCP_INFORM) {
2995 ip4_addr_copy(dhcp->msg_out->ciaddr, *netif_ip4_addr(netif));
2996 }
2997 if (((message_type == DHCP_DECLINE) &&
2998 ((dhcp_state->state == DHCP_STATE_BOUND) ||
2999 (dhcp_state->state == DHCP_STATE_RENEWING) ||
3000 (dhcp_state->state == DHCP_STATE_REBINDING))) ||
3001 (message_type == DHCP_RELEASE) ||
3002 ((message_type == DHCP_REQUEST) && /* DHCP_STATE_BOUND not used for sending! */
3003 ((dhcp_state->state == DHCP_STATE_RENEWING) ||
3004 dhcp_state->state == DHCP_STATE_REBINDING))) {
3005 dhcp_get_client_ip(&cli_ip.addr, dhcp, dhcp_state);
3006 ip4_addr_copy(dhcp->msg_out->ciaddr, cli_ip);
3007 }
3008 ip4_addr_set_zero(&dhcp->msg_out->yiaddr);
3009 ip4_addr_set_zero(&dhcp->msg_out->siaddr);
3010 ip4_addr_set_zero(&dhcp->msg_out->giaddr);
3011 for (i = 0; i < LWIP_MIN(DHCP_CHADDR_LEN, NETIF_MAX_HWADDR_LEN); i++) {
3012 /* copy netif hardware address (padded with zeroes through memset already) */
3013 dhcp->msg_out->chaddr[i] = (u8_t)((i < dhcp_state->hwaddr_len &&
3014 i < NETIF_MAX_HWADDR_LEN) ? dhcp->hwaddr[i] : 0); /* pad byte */
3015 }
3016 for (i = 0; i < DHCP_SNAME_LEN; i++) {
3017 dhcp->msg_out->sname[i] = 0;
3018 }
3019 for (i = 0; i < DHCP_FILE_LEN; i++) {
3020 dhcp->msg_out->file[i] = 0;
3021 }
3022 dhcp->msg_out->cookie = PP_HTONL(DHCP_MAGIC_COOKIE);
3023 dhcp->options_out_len = 0;
3024 /* fill options field with an incrementing array (for debugging purposes) */
3025 for (i = 0; i < DHCP_OPTIONS_LEN; i++) {
3026 dhcp->msg_out->options[i] = (u8_t)i; /* for debugging only, no matter if truncated */
3027 }
3028 /* Add option MESSAGE_TYPE */
3029 options_out_len_loc = dhcp_option(0, dhcp->msg_out->options, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
3030 options_out_len_loc = dhcp_option_byte(options_out_len_loc, dhcp->msg_out->options, message_type);
3031 if (options_out_len) {
3032 *options_out_len = options_out_len_loc;
3033 }
3034 return ERR_OK;
3035 }
3036
3037 /**
3038 * Free previously allocated memory used to send a DHCP request.
3039 *
3040 * @param dhcp the dhcp struct to free the request from
3041 */
3042 static void
dhcp_delete_msg(struct dhcp_client * dhcp)3043 dhcp_delete_msg(struct dhcp_client *dhcp)
3044 {
3045 LWIP_ERROR("dhcp_delete_msg: dhcp != NULL", (dhcp != NULL), return);
3046 LWIP_ASSERT("dhcp_delete_msg: dhcp->p_out != NULL", dhcp->p_out != NULL);
3047 LWIP_ASSERT("dhcp_delete_msg: dhcp->msg_out != NULL", dhcp->msg_out != NULL);
3048 if (dhcp->p_out != NULL) {
3049 (void)pbuf_free(dhcp->p_out);
3050 }
3051 dhcp->p_out = NULL;
3052 dhcp->msg_out = NULL;
3053 }
3054
3055 /**
3056 * Add a DHCP message trailer
3057 *
3058 * Adds the END option to the DHCP message, and if
3059 * necessary, up to three padding bytes.
3060 */
3061 static void
dhcp_option_trailer(u16_t options_out_len,u8_t * options,struct pbuf * p_out)3062 dhcp_option_trailer(u16_t options_out_len, u8_t *options, struct pbuf *p_out)
3063 {
3064 options[options_out_len++] = DHCP_OPTION_END;
3065 /* packet is too small, or not 4 byte aligned? */
3066 while (((options_out_len < DHCP_MIN_OPTIONS_LEN) || (options_out_len & 3)) &&
3067 (options_out_len < DHCP_OPTIONS_LEN)) {
3068 /* add a fill/padding byte */
3069 options[options_out_len++] = 0;
3070 }
3071 /* shrink the pbuf to the actual content length */
3072 pbuf_realloc(p_out, (u16_t)(sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + options_out_len));
3073 }
3074
3075 /** check if DHCP supplied netif->ip_addr
3076 *
3077 * @param netif the netif to check
3078 * @return 1 if DHCP supplied netif->ip_addr (states BOUND or RENEWING),
3079 * 0 otherwise
3080 */
3081 u8_t
dhcp_supplied_address(const struct netif * netif)3082 dhcp_supplied_address(const struct netif *netif)
3083 {
3084 struct dhcp *netif_dhcp = NULL;
3085 struct dhcp_state *dhcp_state = NULL;
3086 if (netif != NULL) {
3087 netif_dhcp = netif_dhcp_data(netif);
3088 if (netif_dhcp == NULL) {
3089 return 0;
3090 }
3091 dhcp_state = &((netif_dhcp->client.states)[LWIP_DHCP_NATIVE_IDX]);
3092 return (u8_t)((dhcp_state->state == DHCP_STATE_BOUND) ||
3093 (dhcp_state->state == DHCP_STATE_RENEWING) ||
3094 (dhcp_state->state == DHCP_STATE_REBINDING));
3095 }
3096 return 0;
3097 }
3098
3099 #if LWIP_DHCP_SUBSTITUTE
3100 #if LWIP_ARP
3101 void
dhcp_events_record(struct netif * netif,u8_t flags)3102 dhcp_events_record(struct netif *netif, u8_t flags)
3103 {
3104 struct dhcp *netif_dhcp = netif_dhcp_data(netif);
3105
3106 if (netif_dhcp == NULL) {
3107 return;
3108 }
3109 netif_dhcp->flags |= flags;
3110 }
3111
3112 static void
dhcp_clients_announce(struct netif * netif)3113 dhcp_clients_announce(struct netif *netif)
3114 {
3115 struct dhcp *netif_dhcp = netif_dhcp_data(netif);
3116 struct dhcp_client *dhcp = &(netif_dhcp->client);
3117 struct dhcp_state *dhcp_state = NULL;
3118 dhcp_num_t i;
3119 u8_t hwaddr_len;
3120
3121 /*
3122 * when hwaddr of netif is changed, for netif's dhcp client, it may keep use its IP
3123 * or restart dhcp client by APP to obtain a new IP
3124 */
3125 for (i = 0; i < DHCP_CLIENT_NUM; i++) {
3126 dhcp_state = &((dhcp->states)[i]);
3127 if ((dhcp_state->state != DHCP_STATE_BOUND) && (dhcp_state->state != DHCP_STATE_RENEWING) &&
3128 (dhcp_state->state != DHCP_STATE_REBINDING)) {
3129 continue;
3130 }
3131 if (dhcp_idx_to_mac(netif, dhcp_state->idx, dhcp->hwaddr, &hwaddr_len) != ERR_OK) {
3132 continue;
3133 }
3134 dhcp->cli_idx = (dhcp_num_t)i;
3135 dhcp_state->hwaddr_len = hwaddr_len;
3136 /*
3137 * set state to be DHCP_STATE_BOUND to send ARP Announce
3138 * states DHCP_STATE_RENEWING or DHCP_STATE_REBINDING can recover later
3139 */
3140 dhcp_set_state(dhcp, DHCP_STATE_BOUND);
3141 /* maybe old state was DHCP_STATE_BOUND, so try times need to reset here */
3142 dhcp_state->tries = 0;
3143 dhcp_announce(netif, dhcp);
3144 }
3145 }
3146
3147 void
dhcp_events_trigger(struct netif * netif)3148 dhcp_events_trigger(struct netif *netif)
3149 {
3150 struct dhcp *netif_dhcp = NULL;
3151
3152 if (!(netif_is_up(netif) && netif_is_link_up(netif))) {
3153 return;
3154 }
3155 netif_dhcp = netif_dhcp_data(netif);
3156 if (netif_dhcp == NULL) {
3157 return;
3158 }
3159 /* currently just support event DHCP_EVENT_HW */
3160 if ((netif_dhcp->flags & DHCP_EVENT_HW) == 0) {
3161 return;
3162 }
3163 if ((netif->flags & NETIF_FLAG_ETHARP) != 0) {
3164 /* hwaddr has been modified, must send ARP Announce */
3165 dhcp_clients_announce(netif);
3166 }
3167
3168 /* clear flag DHCP_EVENT_HW */
3169 netif_dhcp->flags &= ~DHCP_EVENT_HW;
3170 }
3171 #endif /* LWIP_ARP */
3172
3173 static void
dhcp_substitute_clients_restart(struct netif * netif,struct dhcp_client * dhcp)3174 dhcp_substitute_clients_restart(struct netif *netif, struct dhcp_client *dhcp)
3175 {
3176 int i;
3177 u8_t hwaddr_len;
3178 struct dhcp_state *dhcp_state = NULL;
3179
3180 for (i = 1; i < DHCP_CLIENT_NUM; i++) {
3181 dhcp_state = &((dhcp->states)[i]);
3182 if ((dhcp_state->idx == 0)) {
3183 continue;
3184 }
3185 dhcp->cli_idx = (dhcp_num_t)i;
3186 if (dhcp_idx_to_mac(netif, dhcp_state->idx, dhcp->hwaddr, &hwaddr_len) != ERR_OK) {
3187 LWIP_DEBUGF_LOG1(DHCP_DEBUG | LWIP_DBG_TRACE,
3188 "dhcp_substitute_clients_restart(): %u get mac failed\n", dhcp_state->idx);
3189 continue;
3190 }
3191 dhcp_state->hwaddr_len = hwaddr_len;
3192 (void)dhcp_release_client(netif, dhcp);
3193 (void)dhcp_discover(netif, dhcp);
3194 }
3195
3196 return;
3197 }
3198
3199 static s32_t
dhcp_addr_clients_check(struct dhcp * netif_dhcp,const ip4_addr_t * ipaddr)3200 dhcp_addr_clients_check(struct dhcp *netif_dhcp, const ip4_addr_t *ipaddr)
3201 {
3202 struct dhcp_client *dhcp = NULL;
3203 dhcp_num_t offered_ip_addr;
3204 struct dhcp_state *dhcp_state = NULL;
3205 int i;
3206
3207 dhcp = &(netif_dhcp->client);
3208
3209 DHCP_IP_TO_HOST(offered_ip_addr, ipaddr->addr, dhcp->offered_sn_mask.addr);
3210 for (i = 0; i < DHCP_CLIENT_NUM; i++) {
3211 dhcp_state = &((dhcp->states)[i]);
3212 if ((i != LWIP_DHCP_NATIVE_IDX) && (dhcp_state->idx == 0)) {
3213 continue;
3214 }
3215 if ((dhcp_state->state != DHCP_STATE_BOUND) && (dhcp_state->state != DHCP_STATE_RENEWING) &&
3216 (dhcp_state->state != DHCP_STATE_REBINDING)) {
3217 continue;
3218 }
3219 if (dhcp_state->offered_ip_addr == offered_ip_addr) {
3220 LWIP_DEBUGF_LOG1(DHCP_DEBUG | LWIP_DBG_TRACE, "dhcp_addr_clients_check(): %u used by substitute\n", ipaddr->addr);
3221 return lwIP_TRUE;
3222 }
3223 }
3224
3225 return lwIP_FALSE;
3226 }
3227
3228 err_t
dhcp_substitute_start(struct netif * netif,dhcp_num_t mac_idx,u32_t pref_ipv4)3229 dhcp_substitute_start(struct netif *netif, dhcp_num_t mac_idx, u32_t pref_ipv4)
3230 {
3231 err_t err;
3232 LWIP_ERROR("netif != NULL", (netif != NULL), return ERR_ARG);
3233 LWIP_ERROR("netif is not up, old style port?", netif_is_up(netif), return ERR_ARG);
3234 LWIP_ERROR("mac_idx != LWIP_DHCP_NATIVE_IDX", (mac_idx != LWIP_DHCP_NATIVE_IDX), return ERR_ARG);
3235 LWIP_DEBUGF_LOG1(DHCP_DEBUG | LWIP_DBG_TRACE, "dhcp_substitute_start:%u\n", mac_idx);
3236
3237 err = dhcp_start_client(netif, mac_idx, pref_ipv4);
3238 if (err == ERR_OK) {
3239 dhcp_clients_count_update(&(netif_dhcp_data(netif)->client));
3240 }
3241 return err;
3242 }
3243
3244 #if LWIP_DHCP_SUBSTITUTE_MMBR
3245 /*
3246 * send ARP Request to check if there is an another MBR using this IP.
3247 * If receive the ARP Reply, then just think there is a MBR using this IP and should not send the Release message.
3248 * If we send the Release message, it may lead to that MBR renew IP failed and that MBR may get a different IP
3249 * from DHCP server.
3250 */
3251 static void
dhcp_release_check(struct netif * netif,struct dhcp_client * dhcp)3252 dhcp_release_check(struct netif *netif, struct dhcp_client *dhcp)
3253 {
3254 err_t result;
3255 u16_t msecs;
3256 struct dhcp_state *dhcp_state = &((dhcp->states)[dhcp->cli_idx]);
3257 ip4_addr_t cli_ip;
3258 dhcp_set_state(dhcp, DHCP_STATE_RELEASING);
3259 dhcp_get_client_ip(&cli_ip.addr, dhcp, dhcp_state);
3260 result = etharp_request(netif, &cli_ip);
3261 if (result != ERR_OK) {
3262 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
3263 ("dhcp_release_check: could not perform ARP query\n"));
3264 }
3265 if (dhcp_state->tries < 255) {
3266 dhcp_state->tries++;
3267 }
3268 msecs = DHCP_FINE_TIMER_MSECS;
3269 dhcp_state->request_timeout = (u16_t)((msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS);
3270 LWIP_DEBUGF_LOG1(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
3271 "dhcp_release_check(): set request timeout %"U16_F" msecs\n", msecs);
3272 }
3273 #endif /* LWIP_DHCP_SUBSTITUTE_MMBR */
3274
3275 void
dhcp_substitute_stop(struct netif * netif,dhcp_num_t mac_idx,u8_t now)3276 dhcp_substitute_stop(struct netif *netif, dhcp_num_t mac_idx, u8_t now)
3277 {
3278 struct dhcp_client *dhcp = NULL;
3279 struct dhcp *netif_dhcp = NULL;
3280 struct dhcp_state *dhcp_state = NULL;
3281 u8_t hwaddr_len;
3282 (void)now;
3283 LWIP_ERROR("netif != NULL", (netif != NULL), return);
3284 LWIP_ERROR("mac_idx != LWIP_DHCP_NATIVE_IDX", (mac_idx != LWIP_DHCP_NATIVE_IDX), return);
3285 LWIP_DEBUGF_LOG1(DHCP_DEBUG | LWIP_DBG_TRACE, "dhcp_substitute_stop:%u\n", mac_idx);
3286
3287 netif_dhcp = netif_dhcp_data(netif);
3288 if (netif_dhcp == NULL) {
3289 return;
3290 }
3291
3292 dhcp = &(netif_dhcp->client);
3293 if (dhcp_client_find_by_mac_idx(dhcp, mac_idx, &(dhcp->cli_idx)) != ERR_OK) {
3294 LWIP_DEBUGF_LOG1(DHCP_DEBUG | LWIP_DBG_TRACE, "dhcp_substitute_stop(): client state not find for %u\n", mac_idx);
3295 return;
3296 }
3297
3298 dhcp_state = &((dhcp->states)[dhcp->cli_idx]);
3299 if (dhcp_idx_to_mac(netif, dhcp_state->idx, dhcp->hwaddr, &hwaddr_len) != ERR_OK) {
3300 LWIP_DEBUGF_LOG1(DHCP_DEBUG | LWIP_DBG_TRACE, "dhcp_substitute_stop(): no client state for %u\n", mac_idx);
3301 return;
3302 }
3303 dhcp_state->hwaddr_len = hwaddr_len;
3304
3305 #if LWIP_DHCP_SUBSTITUTE_MMBR
3306 if (now == lwIP_FALSE) {
3307 if ((dhcp_state->state == DHCP_STATE_BOUND) ||
3308 (dhcp_state->state == DHCP_STATE_RENEWING) ||
3309 (dhcp_state->state == DHCP_STATE_REBINDING)) {
3310 dhcp_release_check(netif, dhcp);
3311 } else if (dhcp_state->state == DHCP_STATE_RELEASING) {
3312 /* do nothing */
3313 } else {
3314 dhcp_stop_client(netif, dhcp);
3315 }
3316 } else
3317 #endif /* LWIP_DHCP_SUBSTITUTE_MMBR */
3318 {
3319 dhcp_stop_client(netif, dhcp);
3320 }
3321
3322 return;
3323 }
3324
3325 err_t
dhcp_substitute_idx_to_ip(struct netif * netif,dhcp_num_t idx,ip4_addr_t * ip)3326 dhcp_substitute_idx_to_ip(struct netif *netif, dhcp_num_t idx, ip4_addr_t *ip)
3327 {
3328 struct dhcp_client *dhcp = NULL;
3329 struct dhcp *netif_dhcp = NULL;
3330 struct dhcp_state *dhcp_state = NULL;
3331 int i;
3332
3333 LWIP_ERROR("dhcp_substitute_idx_to_ip:netif != NULL", (netif != NULL), return ERR_ARG);
3334 LWIP_ERROR("dhcp_substitute_idx_to_ip:ip != NULL", (ip != NULL), return ERR_ARG);
3335
3336 netif_dhcp = netif_dhcp_data(netif);
3337 if (netif_dhcp == NULL) {
3338 return ERR_VAL;
3339 }
3340 dhcp = &(netif_dhcp->client);
3341
3342 for (i = 0; i < DHCP_CLIENT_NUM; i++) {
3343 dhcp_state = &((dhcp->states)[i]);
3344 if ((dhcp_state->idx != idx)) {
3345 continue;
3346 }
3347 if ((dhcp_state->state != DHCP_STATE_BOUND) && (dhcp_state->state != DHCP_STATE_RENEWING) &&
3348 (dhcp_state->state != DHCP_STATE_REBINDING)) {
3349 return ERR_INPROGRESS;
3350 }
3351 dhcp_get_client_ip(&(ip->addr), dhcp, dhcp_state);
3352 return ERR_OK;
3353 }
3354
3355 return ERR_VAL;
3356 }
3357
3358 static struct dhcp_clients_info *
dhcp_clients_info_fill(struct netif * netif,dhcp_num_t cnt)3359 dhcp_clients_info_fill(struct netif *netif, dhcp_num_t cnt)
3360 {
3361 mem_size_t clis_info_size = sizeof(struct dhcp_clients_info) + cnt * sizeof(struct dhcp_client_mac_info);
3362 struct dhcp_clients_info *clis_info = (struct dhcp_clients_info *)mem_malloc(clis_info_size);
3363 struct dhcp_client_mac_info *cli = NULL;
3364 struct dhcp *netif_dhcp = netif_dhcp_data(netif);
3365 struct dhcp_client *dhcp = &(netif_dhcp->client);
3366 struct dhcp_state *dhcp_state = NULL;
3367 dhcp_num_t i;
3368 dhcp_num_t fill_cnt = 0;
3369 u8_t hwaddr_len;
3370 LWIP_ERROR("dhcp_clients_info_fill:malloc fail\n", (clis_info != NULL), return NULL);
3371
3372 (void)memset_s(clis_info, clis_info_size, 0, clis_info_size);
3373
3374 for (i = 0; (i < DHCP_CLIENT_NUM) && (fill_cnt < cnt); i++) {
3375 dhcp_state = &((dhcp->states)[i]);
3376 if ((i != LWIP_DHCP_NATIVE_IDX) && (dhcp_state->idx == 0)) {
3377 continue;
3378 }
3379 cli = &(clis_info->clis[fill_cnt]);
3380 if (dhcp_idx_to_mac(netif, dhcp_state->idx, cli->mac, &hwaddr_len) != ERR_OK) {
3381 LWIP_DEBUGF_LOG1(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
3382 "dhcp_clients_info_fill:idx %"DHCP_NUM_F" to mac failed\n", dhcp_state->idx);
3383 goto failure;
3384 }
3385 cli->mac_len = hwaddr_len;
3386 fill_cnt++;
3387 }
3388 clis_info->num = fill_cnt;
3389 return clis_info;
3390 failure:
3391 mem_free(clis_info);
3392 return NULL;
3393 }
3394
3395 err_t
dhcp_clients_info_get(struct netif * netif,void * arg)3396 dhcp_clients_info_get(struct netif *netif, void *arg)
3397 {
3398 struct dhcp_clients_info **clis_info = (struct dhcp_clients_info **)arg;
3399 struct dhcp *netif_dhcp = NULL;
3400
3401 LWIP_ERROR("dhcp_clients_info_get:netif != NULL\n", (netif != NULL), return ERR_ARG);
3402 LWIP_ERROR("dhcp_clients_info_get:clis_info != NULL\n", (clis_info != NULL), return ERR_ARG);
3403 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_clients_info_get:%s%hhu\n", netif->name, netif->num));
3404 netif_dhcp = netif_dhcp_data(netif);
3405 if (netif_dhcp == NULL) {
3406 return ERR_VAL;
3407 }
3408 if (netif_dhcp->clis_info != NULL) {
3409 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_clients_info_get:last not free\n"));
3410 return ERR_INPROGRESS;
3411 }
3412
3413 if (netif_dhcp->client.cli_cnt == 0) {
3414 return ERR_VAL;
3415 }
3416 *clis_info = dhcp_clients_info_fill(netif, netif_dhcp->client.cli_cnt);
3417 if (*clis_info == NULL) {
3418 return ERR_MEM;
3419 }
3420 netif_dhcp->clis_info = *clis_info;
3421 return ERR_OK;
3422 }
3423
3424 err_t
dhcp_clients_info_free(struct netif * netif,void * arg)3425 dhcp_clients_info_free(struct netif *netif, void *arg)
3426 {
3427 struct dhcp_clients_info **clis_info = (struct dhcp_clients_info **)arg;
3428 struct dhcp *netif_dhcp = NULL;
3429 LWIP_ERROR("dhcp_clients_info_free:netif != NULL\n", (netif != NULL), return ERR_ARG);
3430 LWIP_ERROR("dhcp_clients_info_free:clis_info != NULL\n", (clis_info != NULL), return ERR_ARG);
3431 LWIP_ERROR("dhcp_clients_info_free:*clis_info != NULL\n", (*clis_info != NULL), return ERR_ARG);
3432 netif_dhcp = netif_dhcp_data(netif);
3433 if (netif_dhcp == NULL) {
3434 return ERR_VAL;
3435 }
3436 if (netif_dhcp->clis_info != (*clis_info)) {
3437 return ERR_VAL;
3438 }
3439 mem_free(*clis_info);
3440 *clis_info = NULL;
3441 netif_dhcp->clis_info = NULL;
3442
3443 return ERR_OK;
3444 }
3445
3446 static void
dhcp_client_info_fill_ip4(struct dhcp_client_info * cli_info,struct dhcp_client * dhcp)3447 dhcp_client_info_fill_ip4(struct dhcp_client_info *cli_info, struct dhcp_client *dhcp)
3448 {
3449 struct dhcp_state *dhcp_state = &((dhcp->states)[dhcp->cli_idx]);
3450
3451 if ((dhcp_state->state == DHCP_STATE_BOUND) || (dhcp_state->state == DHCP_STATE_RENEWING) ||
3452 (dhcp_state->state == DHCP_STATE_REBINDING)) {
3453 dhcp_get_client_ip(&(cli_info->ip4addr.addr), dhcp, dhcp_state);
3454 } else {
3455 ip4_addr_set_any(&(cli_info->ip4addr));
3456 }
3457 }
3458
3459 static err_t
dhcp_native_ip6addr_get(struct dhcp_client_info * cli_info)3460 dhcp_native_ip6addr_get(struct dhcp_client_info *cli_info)
3461 {
3462 #if LWIP_RIPPLE
3463 struct netif *netif = (struct netif *)rpl_platform_get_dev();
3464 u8_t i;
3465 if (netif == NULL) {
3466 return ERR_VAL;
3467 }
3468 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
3469 if (ip6_addr_isinvalid(netif_ip6_addr_state(netif, i))) {
3470 continue;
3471 }
3472 if (ip6_addr_islinklocal(netif_ip6_addr(netif, i))) {
3473 continue;
3474 }
3475 (void)memcpy_s(&(cli_info->ip6addr), sizeof(ip6_addr_t), netif_ip6_addr(netif, i), sizeof(ip6_addr_t));
3476 return ERR_OK;
3477 }
3478 return ERR_VAL;
3479 #else
3480 (void)cli_info;
3481 return ERR_VAL;
3482 #endif
3483 }
3484
3485 static err_t
dhcp_client_info_fill_ip6(struct dhcp_client_info * cli_info,struct dhcp_client * dhcp)3486 dhcp_client_info_fill_ip6(struct dhcp_client_info *cli_info, struct dhcp_client *dhcp)
3487 {
3488 if (dhcp->cli_idx == LWIP_DHCP_NATIVE_IDX) {
3489 return dhcp_native_ip6addr_get(cli_info);
3490 } else {
3491 #if LWIP_NAT64
3492 struct dhcp_state *dhcp_state = &((dhcp->states)[dhcp->cli_idx]);
3493 if (nat64_entry_idx_to_ip6addr(dhcp_state->idx, &(cli_info->ip6addr))) {
3494 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
3495 "dhcp_client_info_fill_ip6:get ip6addr failed\n");
3496 return ERR_VAL;
3497 }
3498 #else
3499 return ERR_VAL;
3500 #endif
3501 }
3502 return ERR_OK;
3503 }
3504
3505 static err_t
dhcp_client_info_fill(struct dhcp_client_info * cli_info,struct dhcp_client * dhcp)3506 dhcp_client_info_fill(struct dhcp_client_info *cli_info, struct dhcp_client *dhcp)
3507 {
3508 dhcp_client_info_fill_ip4(cli_info, dhcp);
3509
3510 return dhcp_client_info_fill_ip6(cli_info, dhcp);
3511 }
3512
3513 err_t
dhcp_client_info_find(struct netif * netif,void * cli_info)3514 dhcp_client_info_find(struct netif *netif, void *cli_info)
3515 {
3516 struct dhcp_client_info *cli_info_p = (struct dhcp_client_info *)cli_info;
3517 err_t err;
3518 struct dhcp *netif_dhcp = NULL;
3519 dhcp_num_t mac_idx;
3520
3521 LWIP_ERROR("dhcp_client_info_find:netif != NULL\n", (netif != NULL), return ERR_ARG);
3522 LWIP_ERROR("dhcp_client_info_find:cli_info_p != NULL\n", (cli_info_p != NULL), return ERR_ARG);
3523 netif_dhcp = netif_dhcp_data(netif);
3524 if (netif_dhcp == NULL) {
3525 return ERR_VAL;
3526 }
3527
3528 err = dhcp_mac_to_idx(netif, cli_info_p->mac, cli_info_p->mac_len, &mac_idx);
3529 if (err != ERR_OK) {
3530 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_client_info_find(): mac idx failed\n"));
3531 return ERR_VAL;
3532 }
3533
3534 if (dhcp_client_find_by_mac_idx(&(netif_dhcp->client), mac_idx, &(netif_dhcp->client.cli_idx)) != ERR_OK) {
3535 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_recv(): no client\n"));
3536 return ERR_VAL;
3537 }
3538
3539 return dhcp_client_info_fill(cli_info_p, &(netif_dhcp->client));
3540 }
3541
3542 #if LWIP_ENABLE_BASIC_SHELL_CMD
3543 s32_t
dhcp_netif_addr_clients_check(const struct netif * netif,const ip4_addr_t * ipaddr)3544 dhcp_netif_addr_clients_check(const struct netif *netif, const ip4_addr_t *ipaddr)
3545 {
3546 struct dhcp *netif_dhcp = NULL;
3547
3548 if ((netif == NULL) || (ipaddr == NULL)) {
3549 return lwIP_FALSE;
3550 }
3551
3552 netif_dhcp = netif_dhcp_data(netif);
3553 if (netif_dhcp == NULL) {
3554 return lwIP_FALSE;
3555 }
3556
3557 return dhcp_addr_clients_check(netif_dhcp, ipaddr);
3558 }
3559 #endif /* LWIP_ENABLE_BASIC_SHELL_CMD */
3560
3561 #if LWIP_DHCP_LIMIT_CONCURRENT_REQUESTS
3562 static void
dhcp_concurrent_limit_wait_timeout(struct netif * netif,struct dhcp_client * dhcp)3563 dhcp_concurrent_limit_wait_timeout(struct netif *netif, struct dhcp_client *dhcp)
3564 {
3565 if (dhcp_concurrent_start_client(dhcp) != ERR_OK) {
3566 return;
3567 }
3568 if (!netif_is_link_up(netif)) {
3569 /* set state INIT and wait for dhcp_network_changed() to call dhcp_discover() */
3570 dhcp_set_state(dhcp, DHCP_STATE_INIT);
3571 return;
3572 }
3573
3574 (void)dhcp_discover(netif, dhcp);
3575
3576 return;
3577 }
3578
3579 static u8_t
dhcp_client_request_processing(u8_t state)3580 dhcp_client_request_processing(u8_t state)
3581 {
3582 u8_t is_processing;
3583
3584 switch (state) {
3585 case DHCP_STATE_REQUESTING:
3586 case DHCP_STATE_INIT:
3587 case DHCP_STATE_REBOOTING:
3588 case DHCP_STATE_SELECTING:
3589 case DHCP_STATE_CHECKING:
3590 case DHCP_STATE_BACKING_OFF:
3591 is_processing = lwIP_TRUE;
3592 break;
3593 default:
3594 is_processing = lwIP_FALSE;
3595 break;
3596 }
3597
3598 return is_processing;
3599 }
3600
3601 static err_t
dhcp_concurrent_start_client(struct dhcp_client * dhcp)3602 dhcp_concurrent_start_client(struct dhcp_client *dhcp)
3603 {
3604 struct dhcp_state *dhcp_state = &((dhcp->states)[dhcp->cli_idx]);
3605 if (g_dhcp_max_concurrent_num != 0) {
3606 if (dhcp->rqst_cli_cnt >= g_dhcp_max_concurrent_num) {
3607 dhcp_set_state(dhcp, DHCP_STATE_LIMIT_WAIT);
3608 dhcp_state->request_timeout = 1;
3609 return ERR_INPROGRESS;
3610 }
3611 dhcp->rqst_cli_cnt++;
3612 }
3613 return ERR_OK;
3614 }
3615
3616 static void
dhcp_concurrent_stop_client(struct dhcp_client * dhcp)3617 dhcp_concurrent_stop_client(struct dhcp_client *dhcp)
3618 {
3619 struct dhcp_state *dhcp_state = &((dhcp->states)[dhcp->cli_idx]);
3620
3621 if (g_dhcp_max_concurrent_num == 0) {
3622 return;
3623 }
3624
3625 if (dhcp_client_request_processing(dhcp_state->state) == lwIP_TRUE) {
3626 dhcp->rqst_cli_cnt--;
3627 }
3628
3629 return;
3630 }
3631
3632 static void
dhcp_concurrent_start_next_client(struct netif * netif,u8_t all)3633 dhcp_concurrent_start_next_client(struct netif *netif, u8_t all)
3634 {
3635 struct dhcp *netif_dhcp = netif_dhcp_data(netif);
3636 struct dhcp_state *dhcp_state = NULL;
3637 int i;
3638 u8_t hwaddr_len;
3639
3640 for (i = 0; i < DHCP_CLIENT_NUM; i++) {
3641 netif_dhcp->client.cli_idx = (dhcp_num_t)i;
3642 dhcp_state = &((netif_dhcp->client.states)[i]);
3643 if ((i != LWIP_DHCP_NATIVE_IDX) && (dhcp_state->idx == 0)) {
3644 continue;
3645 }
3646 if (dhcp_state->state != DHCP_STATE_LIMIT_WAIT) {
3647 continue;
3648 }
3649 if (dhcp_idx_to_mac(netif, dhcp_state->idx, netif_dhcp->client.hwaddr, &hwaddr_len) != ERR_OK) {
3650 LWIP_DEBUGF_LOG1(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
3651 "dhcp_concurrent_start_next_client:idx %u to mac failed\n", dhcp_state->idx);
3652 continue;
3653 }
3654 dhcp_state->hwaddr_len = hwaddr_len;
3655 (void)dhcp_discover(netif, &(netif_dhcp->client));
3656 if (all == lwIP_FALSE) {
3657 (netif_dhcp->client.rqst_cli_cnt)++;
3658 break;
3659 }
3660 }
3661
3662 return;
3663 }
3664
3665 static void
dhcp_concurrent_num_update(struct dhcp_client * dhcp)3666 dhcp_concurrent_num_update(struct dhcp_client *dhcp)
3667 {
3668 struct dhcp_state *dhcp_state = NULL;
3669 int i;
3670
3671 dhcp->rqst_cli_cnt = 0;
3672 for (i = 0; i < DHCP_CLIENT_NUM; i++) {
3673 dhcp->cli_idx = (dhcp_num_t)i;
3674 dhcp_state = &((dhcp->states)[i]);
3675 if ((i != LWIP_DHCP_NATIVE_IDX) && (dhcp_state->idx == 0)) {
3676 continue;
3677 }
3678 if (dhcp_client_request_processing(dhcp_state->state) == lwIP_FALSE) {
3679 continue;
3680 }
3681 if (dhcp->rqst_cli_cnt < g_dhcp_max_concurrent_num) {
3682 dhcp->rqst_cli_cnt++;
3683 } else {
3684 dhcp_set_state(dhcp, DHCP_STATE_LIMIT_WAIT);
3685 dhcp_state->request_timeout = 1;
3686 }
3687 }
3688
3689 return;
3690 }
3691
3692 err_t
dhcp_set_max_concurrent_num(struct netif * netif,u16_t dhcp_max_concurrent_num)3693 dhcp_set_max_concurrent_num(struct netif *netif, u16_t dhcp_max_concurrent_num)
3694 {
3695 struct dhcp *netif_dhcp = NULL;
3696 struct dhcp_client *dhcp = NULL;
3697
3698 LWIP_DEBUGF_LOG0(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_set_max_concurrent_num()\n"));
3699 LWIP_ERROR("netif != NULL", (netif != NULL), return ERR_ARG);
3700 netif_dhcp = netif_dhcp_data(netif);
3701 LWIP_ERROR("netif_dhcp != NULL", (netif_dhcp != NULL), return ERR_VAL);
3702
3703 dhcp = &(netif_dhcp->client);
3704 if (dhcp_max_concurrent_num == 0) {
3705 g_dhcp_max_concurrent_num = 0;
3706 dhcp->rqst_cli_cnt = 0;
3707 dhcp_concurrent_start_next_client(netif, lwIP_TRUE);
3708 } else {
3709 g_dhcp_max_concurrent_num = dhcp_max_concurrent_num;
3710 dhcp_concurrent_num_update(dhcp);
3711 }
3712
3713 return ERR_OK;
3714 }
3715 #endif /* LWIP_DHCP_LIMIT_CONCURRENT_REQUESTS */
3716 #endif /* LWIP_DHCP_SUBSTITUTE */
3717
3718 #endif /* LWIP_IPV4 && LWIP_DHCP */
3719