source: azure_iot_hub_f767zi/trunk/asp_baseplatform/lwip/lwip-2.1.2/src/core/ipv4/dhcp.c@ 457

Last change on this file since 457 was 457, checked in by coas-nagasima, 4 years ago

ファイルを追加

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