4 * Dynamic Host Configuration Protocol client
9 * Copyright (c) 2001-2004 Leon Woestenberg <leon.woestenberg@gmx.net>
10 * Copyright (c) 2001-2004 Axon Digital Design B.V., The Netherlands.
11 * All rights reserved.
13 * Redistribution and use in source and binary forms, with or without modification,
14 * are permitted provided that the following conditions are met:
16 * 1. Redistributions of source code must retain the above copyright notice,
17 * this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright notice,
19 * this list of conditions and the following disclaimer in the documentation
20 * and/or other materials provided with the distribution.
21 * 3. The name of the author may not be used to endorse or promote products
22 * derived from this software without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
25 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
26 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
27 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
29 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
32 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
35 * This file is a contribution to the lwIP TCP/IP stack.
36 * The Swedish Institute of Computer Science and Adam Dunkels
37 * are specifically granted permission to redistribute this
40 * Author: Leon Woestenberg <leon.woestenberg@gmx.net>
42 * This is a DHCP client for the lwIP TCP/IP stack. It aims to conform
43 * with RFC 2131 and RFC 2132.
46 * - Proper parsing of DHCP messages exploiting file/sname field overloading.
47 * - Add JavaDoc style documentation (API, internals).
48 * - Support for interfaces other than Ethernet (SLIP, PPP, ...)
50 * Please coordinate changes and requests with Leon Woestenberg
51 * <leon.woestenberg@gmx.net>
53 * Integration with your code:
56 * #define DHCP_COARSE_TIMER_SECS (recommended 60 which is a minute)
57 * #define DHCP_FINE_TIMER_MSECS (recommended 500 which equals TCP coarse timer)
59 * Then have your application call dhcp_coarse_tmr() and
60 * dhcp_fine_tmr() on the defined intervals.
62 * dhcp_start(struct netif *netif);
63 * starts a DHCP client instance which configures the interface by
64 * obtaining an IP address lease and maintaining it.
66 * Use dhcp_release(netif) to end the lease and use dhcp_stop(netif)
67 * to remove the DHCP client.
73 #include "lwip/stats.h"
76 #include "lwip/ip_addr.h"
77 #include "lwip/netif.h"
78 #include "lwip/inet.h"
79 #include "netif/etharp.h"
83 #include "lwip/dhcp.h"
85 #if LWIP_DHCP /* don't build if not configured for use in lwipopt.h */
87 /** global transaction identifier, must be
88 * unique for each DHCP request. We simply increment, starting
89 * with this value (easy to match with a packet analyzer) */
90 static u32_t xid
= 0xABCD0000;
92 /** DHCP client state machine functions */
93 static void dhcp_handle_ack(struct netif
*netif
);
94 static void dhcp_handle_nak(struct netif
*netif
);
95 static void dhcp_handle_offer(struct netif
*netif
);
97 static err_t
dhcp_discover(struct netif
*netif
);
98 static err_t
dhcp_select(struct netif
*netif
);
99 static void dhcp_check(struct netif
*netif
);
100 static void dhcp_bind(struct netif
*netif
);
101 static err_t
dhcp_decline(struct netif
*netif
);
102 static err_t
dhcp_rebind(struct netif
*netif
);
103 static void dhcp_set_state(struct dhcp
*dhcp
, u8_t new_state
);
105 /** receive, unfold, parse and free incoming messages */
106 static void dhcp_recv(void *arg
, struct udp_pcb
*pcb
, struct pbuf
*p
, struct ip_addr
*addr
, u16_t port
);
107 static err_t
dhcp_unfold_reply(struct dhcp
*dhcp
);
108 static u8_t
*dhcp_get_option_ptr(struct dhcp
*dhcp
, u8_t option_type
);
109 static u8_t
dhcp_get_option_byte(u8_t
*ptr
);
110 //static u16_t dhcp_get_option_short(u8_t *ptr);
111 static u32_t
dhcp_get_option_long(u8_t
*ptr
);
112 static void dhcp_free_reply(struct dhcp
*dhcp
);
114 /** set the DHCP timers */
115 static void dhcp_timeout(struct netif
*netif
);
116 static void dhcp_t1_timeout(struct netif
*netif
);
117 static void dhcp_t2_timeout(struct netif
*netif
);
119 /** build outgoing messages */
120 /** create a DHCP request, fill in common headers */
121 static err_t
dhcp_create_request(struct netif
*netif
);
122 /** free a DHCP request */
123 static void dhcp_delete_request(struct netif
*netif
);
124 /** add a DHCP option (type, then length in bytes) */
125 static void dhcp_option(struct dhcp
*dhcp
, u8_t option_type
, u8_t option_len
);
126 /** add option values */
127 static void dhcp_option_byte(struct dhcp
*dhcp
, u8_t value
);
128 static void dhcp_option_short(struct dhcp
*dhcp
, u16_t value
);
129 static void dhcp_option_long(struct dhcp
*dhcp
, u32_t value
);
130 /** always add the DHCP options trailer to end and pad */
131 static void dhcp_option_trailer(struct dhcp
*dhcp
);
134 * Back-off the DHCP client (because of a received NAK response).
136 * Back-off the DHCP client because of a received NAK. Receiving a
137 * NAK means the client asked for something non-sensible, for
138 * example when it tries to renew a lease obtained on another network.
140 * We back-off and will end up restarting a fresh DHCP negotiation later.
142 * @param state pointer to DHCP state structure
144 static void dhcp_handle_nak(struct netif
*netif
) {
145 struct dhcp
*dhcp
= netif
->dhcp
;
146 u16_t msecs
= 10 * 1000;
147 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| 3, ("dhcp_handle_nak(netif=%p) %c%c%"U16_F
"\n",
148 (void*)netif
, netif
->name
[0], netif
->name
[1], (u16_t
)netif
->num
));
149 dhcp
->request_timeout
= (msecs
+ DHCP_FINE_TIMER_MSECS
- 1) / DHCP_FINE_TIMER_MSECS
;
150 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| DBG_STATE
, ("dhcp_handle_nak(): set request timeout %"U16_F
" msecs\n", msecs
));
151 dhcp_set_state(dhcp
, DHCP_BACKING_OFF
);
155 * Checks if the offered IP address is already in use.
157 * It does so by sending an ARP request for the offered address and
158 * entering CHECKING state. If no ARP reply is received within a small
159 * interval, the address is assumed to be free for use by us.
161 static void dhcp_check(struct netif
*netif
)
163 struct dhcp
*dhcp
= netif
->dhcp
;
166 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| 3, ("dhcp_check(netif=%p) %c%c\n", (void *)netif
, (s16_t
)netif
->name
[0],
167 (s16_t
)netif
->name
[1]));
168 /* create an ARP query for the offered IP address, expecting that no host
169 responds, as the IP address should not be in use. */
170 result
= etharp_query(netif
, &dhcp
->offered_ip_addr
, NULL
);
171 if (result
!= ERR_OK
) {
172 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| 2, ("dhcp_check: could not perform ARP query\n"));
176 dhcp
->request_timeout
= (msecs
+ DHCP_FINE_TIMER_MSECS
- 1) / DHCP_FINE_TIMER_MSECS
;
177 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| DBG_STATE
, ("dhcp_check(): set request timeout %"U16_F
" msecs\n", msecs
));
178 dhcp_set_state(dhcp
, DHCP_CHECKING
);
182 * Remember the configuration offered by a DHCP server.
184 * @param state pointer to DHCP state structure
186 static void dhcp_handle_offer(struct netif
*netif
)
188 struct dhcp
*dhcp
= netif
->dhcp
;
189 /* obtain the server address */
190 u8_t
*option_ptr
= dhcp_get_option_ptr(dhcp
, DHCP_OPTION_SERVER_ID
);
191 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| 3, ("dhcp_handle_offer(netif=%p) %c%c%"U16_F
"\n",
192 (void*)netif
, netif
->name
[0], netif
->name
[1], (u16_t
)netif
->num
));
193 if (option_ptr
!= NULL
)
195 dhcp
->server_ip_addr
.addr
= htonl(dhcp_get_option_long(&option_ptr
[2]));
196 LWIP_DEBUGF(DHCP_DEBUG
| DBG_STATE
, ("dhcp_handle_offer(): server 0x%08"X32_F
"\n", dhcp
->server_ip_addr
.addr
));
197 /* remember offered address */
198 ip_addr_set(&dhcp
->offered_ip_addr
, (struct ip_addr
*)&dhcp
->msg_in
->yiaddr
);
199 LWIP_DEBUGF(DHCP_DEBUG
| DBG_STATE
, ("dhcp_handle_offer(): offer for 0x%08"X32_F
"\n", dhcp
->offered_ip_addr
.addr
));
206 * Select a DHCP server offer out of all offers.
208 * Simply select the first offer received.
210 * @param netif the netif under DHCP control
211 * @return lwIP specific error (see error.h)
213 static err_t
dhcp_select(struct netif
*netif
)
215 struct dhcp
*dhcp
= netif
->dhcp
;
218 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| 3, ("dhcp_select(netif=%p) %c%c%"U16_F
"\n", (void*)netif
, netif
->name
[0], netif
->name
[1], (u16_t
)netif
->num
));
220 /* create and initialize the DHCP message header */
221 result
= dhcp_create_request(netif
);
222 if (result
== ERR_OK
)
224 dhcp_option(dhcp
, DHCP_OPTION_MESSAGE_TYPE
, DHCP_OPTION_MESSAGE_TYPE_LEN
);
225 dhcp_option_byte(dhcp
, DHCP_REQUEST
);
227 dhcp_option(dhcp
, DHCP_OPTION_MAX_MSG_SIZE
, DHCP_OPTION_MAX_MSG_SIZE_LEN
);
228 dhcp_option_short(dhcp
, 576);
230 /* MUST request the offered IP address */
231 dhcp_option(dhcp
, DHCP_OPTION_REQUESTED_IP
, 4);
232 dhcp_option_long(dhcp
, ntohl(dhcp
->offered_ip_addr
.addr
));
234 dhcp_option(dhcp
, DHCP_OPTION_SERVER_ID
, 4);
235 dhcp_option_long(dhcp
, ntohl(dhcp
->server_ip_addr
.addr
));
237 dhcp_option(dhcp
, DHCP_OPTION_PARAMETER_REQUEST_LIST
, 4/*num options*/);
238 dhcp_option_byte(dhcp
, DHCP_OPTION_SUBNET_MASK
);
239 dhcp_option_byte(dhcp
, DHCP_OPTION_ROUTER
);
240 dhcp_option_byte(dhcp
, DHCP_OPTION_BROADCAST
);
241 dhcp_option_byte(dhcp
, DHCP_OPTION_DNS_SERVER
);
243 dhcp_option_trailer(dhcp
);
244 /* shrink the pbuf to the actual content length */
245 pbuf_realloc(dhcp
->p_out
, sizeof(struct dhcp_msg
) - DHCP_OPTIONS_LEN
+ dhcp
->options_out_len
);
247 /* TODO: we really should bind to a specific local interface here
248 but we cannot specify an unconfigured netif as it is addressless */
249 udp_bind(dhcp
->pcb
, IP_ADDR_ANY
, DHCP_CLIENT_PORT
);
250 /* send broadcast to any DHCP server */
251 udp_connect(dhcp
->pcb
, IP_ADDR_BROADCAST
, DHCP_SERVER_PORT
);
252 udp_send(dhcp
->pcb
, dhcp
->p_out
);
253 /* reconnect to any (or to server here?!) */
254 udp_connect(dhcp
->pcb
, IP_ADDR_ANY
, DHCP_SERVER_PORT
);
255 dhcp_delete_request(netif
);
256 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| DBG_STATE
, ("dhcp_select: REQUESTING\n"));
257 dhcp_set_state(dhcp
, DHCP_REQUESTING
);
259 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| 2, ("dhcp_select: could not allocate DHCP request\n"));
262 msecs
= dhcp
->tries
< 4 ? dhcp
->tries
* 1000 : 4 * 1000;
263 dhcp
->request_timeout
= (msecs
+ DHCP_FINE_TIMER_MSECS
- 1) / DHCP_FINE_TIMER_MSECS
;
264 LWIP_DEBUGF(DHCP_DEBUG
| DBG_STATE
, ("dhcp_select(): set request timeout %"U32_F
" msecs\n", msecs
));
269 * The DHCP timer that checks for lease renewal/rebind timeouts.
272 void dhcp_coarse_tmr()
274 struct netif
*netif
= netif_list
;
275 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
, ("dhcp_coarse_tmr()\n"));
276 /* iterate through all network interfaces */
277 while (netif
!= NULL
) {
278 /* only act on DHCP configured interfaces */
279 if (netif
->dhcp
!= NULL
) {
280 /* timer is active (non zero), and triggers (zeroes) now? */
281 if (netif
->dhcp
->t2_timeout
-- == 1) {
282 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| DBG_STATE
, ("dhcp_coarse_tmr(): t2 timeout\n"));
283 /* this clients' rebind timeout triggered */
284 dhcp_t2_timeout(netif
);
285 /* timer is active (non zero), and triggers (zeroes) now */
286 } else if (netif
->dhcp
->t1_timeout
-- == 1) {
287 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| DBG_STATE
, ("dhcp_coarse_tmr(): t1 timeout\n"));
288 /* this clients' renewal timeout triggered */
289 dhcp_t1_timeout(netif
);
292 /* proceed to next netif */
298 * DHCP transaction timeout handling
300 * A DHCP server is expected to respond within a short period of time.
301 * This timer checks whether an outstanding DHCP request is timed out.
306 struct netif
*netif
= netif_list
;
307 /* loop through netif's */
308 while (netif
!= NULL
) {
309 /* only act on DHCP configured interfaces */
310 if (netif
->dhcp
!= NULL
) {
311 /* timer is active (non zero), and is about to trigger now */
312 if (netif
->dhcp
->request_timeout
-- == 1) {
313 /* { netif->dhcp->request_timeout == 0 } */
314 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| DBG_STATE
, ("dhcp_fine_tmr(): request timeout\n"));
315 /* this clients' request timeout triggered */
319 /* proceed to next network interface */
325 * A DHCP negotiation transaction, or ARP request, has timed out.
327 * The timer that was started with the DHCP or ARP request has
328 * timed out, indicating no response was received in time.
330 * @param netif the netif under DHCP control
333 static void dhcp_timeout(struct netif
*netif
)
335 struct dhcp
*dhcp
= netif
->dhcp
;
336 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| 3, ("dhcp_timeout()\n"));
337 /* back-off period has passed, or server selection timed out */
338 if ((dhcp
->state
== DHCP_BACKING_OFF
) || (dhcp
->state
== DHCP_SELECTING
)) {
339 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
, ("dhcp_timeout(): restarting discovery\n"));
340 dhcp_discover(netif
);
341 /* receiving the requested lease timed out */
342 } else if (dhcp
->state
== DHCP_REQUESTING
) {
343 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| DBG_STATE
, ("dhcp_timeout(): REQUESTING, DHCP request timed out\n"));
344 if (dhcp
->tries
<= 5) {
347 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| DBG_STATE
, ("dhcp_timeout(): REQUESTING, releasing, restarting\n"));
349 dhcp_discover(netif
);
351 /* received no ARP reply for the offered address (which is good) */
352 } else if (dhcp
->state
== DHCP_CHECKING
) {
353 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| DBG_STATE
, ("dhcp_timeout(): CHECKING, ARP request timed out\n"));
354 if (dhcp
->tries
<= 1) {
356 /* no ARP replies on the offered address,
357 looks like the IP address is indeed free */
359 /* bind the interface to the offered address */
363 /* did not get response to renew request? */
364 else if (dhcp
->state
== DHCP_RENEWING
) {
365 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| DBG_STATE
, ("dhcp_timeout(): RENEWING, DHCP request timed out\n"));
366 /* just retry renewal */
367 /* note that the rebind timer will eventually time-out if renew does not work */
369 /* did not get response to rebind request? */
370 } else if (dhcp
->state
== DHCP_REBINDING
) {
371 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| DBG_STATE
, ("dhcp_timeout(): REBINDING, DHCP request timed out\n"));
372 if (dhcp
->tries
<= 8) {
375 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| DBG_STATE
, ("dhcp_timeout(): RELEASING, DISCOVERING\n"));
377 dhcp_discover(netif
);
383 * The renewal period has timed out.
385 * @param netif the netif under DHCP control
387 static void dhcp_t1_timeout(struct netif
*netif
)
389 struct dhcp
*dhcp
= netif
->dhcp
;
390 LWIP_DEBUGF(DHCP_DEBUG
| DBG_STATE
, ("dhcp_t1_timeout()\n"));
391 if ((dhcp
->state
== DHCP_REQUESTING
) || (dhcp
->state
== DHCP_BOUND
) || (dhcp
->state
== DHCP_RENEWING
)) {
392 /* just retry to renew - note that the rebind timer (t2) will
393 * eventually time-out if renew tries fail. */
394 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| DBG_STATE
, ("dhcp_t1_timeout(): must renew\n"));
400 * The rebind period has timed out.
403 static void dhcp_t2_timeout(struct netif
*netif
)
405 struct dhcp
*dhcp
= netif
->dhcp
;
406 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| DBG_STATE
, ("dhcp_t2_timeout()\n"));
407 if ((dhcp
->state
== DHCP_REQUESTING
) || (dhcp
->state
== DHCP_BOUND
) || (dhcp
->state
== DHCP_RENEWING
)) {
408 /* just retry to rebind */
409 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| DBG_STATE
, ("dhcp_t2_timeout(): must rebind\n"));
416 * @param netif the netif under DHCP control
418 static void dhcp_handle_ack(struct netif
*netif
)
420 struct dhcp
*dhcp
= netif
->dhcp
;
422 /* clear options we might not get from the ACK */
423 dhcp
->offered_sn_mask
.addr
= 0;
424 dhcp
->offered_gw_addr
.addr
= 0;
425 dhcp
->offered_bc_addr
.addr
= 0;
427 /* lease time given? */
428 option_ptr
= dhcp_get_option_ptr(dhcp
, DHCP_OPTION_LEASE_TIME
);
429 if (option_ptr
!= NULL
) {
430 /* remember offered lease time */
431 dhcp
->offered_t0_lease
= dhcp_get_option_long(option_ptr
+ 2);
433 /* renewal period given? */
434 option_ptr
= dhcp_get_option_ptr(dhcp
, DHCP_OPTION_T1
);
435 if (option_ptr
!= NULL
) {
436 /* remember given renewal period */
437 dhcp
->offered_t1_renew
= dhcp_get_option_long(option_ptr
+ 2);
439 /* calculate safe periods for renewal */
440 dhcp
->offered_t1_renew
= dhcp
->offered_t0_lease
/ 2;
443 /* renewal period given? */
444 option_ptr
= dhcp_get_option_ptr(dhcp
, DHCP_OPTION_T2
);
445 if (option_ptr
!= NULL
) {
446 /* remember given rebind period */
447 dhcp
->offered_t2_rebind
= dhcp_get_option_long(option_ptr
+ 2);
449 /* calculate safe periods for rebinding */
450 dhcp
->offered_t2_rebind
= dhcp
->offered_t0_lease
;
453 /* (y)our internet address */
454 ip_addr_set(&dhcp
->offered_ip_addr
, &dhcp
->msg_in
->yiaddr
);
458 * TODO: we must check if the file field is not overloaded by DHCP options!
461 /* boot server address */
462 ip_addr_set(&dhcp
->offered_si_addr
, &dhcp
->msg_in
->siaddr
);
464 if (dhcp
->msg_in
->file
[0]) {
465 dhcp
->boot_file_name
= mem_malloc(strlen(dhcp
->msg_in
->file
) + 1);
466 strcpy(dhcp
->boot_file_name
, dhcp
->msg_in
->file
);
471 option_ptr
= dhcp_get_option_ptr(dhcp
, DHCP_OPTION_SUBNET_MASK
);
472 /* subnet mask given? */
473 if (option_ptr
!= NULL
) {
474 dhcp
->offered_sn_mask
.addr
= htonl(dhcp_get_option_long(&option_ptr
[2]));
478 option_ptr
= dhcp_get_option_ptr(dhcp
, DHCP_OPTION_ROUTER
);
479 if (option_ptr
!= NULL
) {
480 dhcp
->offered_gw_addr
.addr
= htonl(dhcp_get_option_long(&option_ptr
[2]));
483 /* broadcast address */
484 option_ptr
= dhcp_get_option_ptr(dhcp
, DHCP_OPTION_BROADCAST
);
485 if (option_ptr
!= NULL
) {
486 dhcp
->offered_bc_addr
.addr
= htonl(dhcp_get_option_long(&option_ptr
[2]));
490 option_ptr
= dhcp_get_option_ptr(dhcp
, DHCP_OPTION_DNS_SERVER
);
491 if (option_ptr
!= NULL
) {
493 dhcp
->dns_count
= dhcp_get_option_byte(&option_ptr
[1]);
494 /* limit to at most DHCP_MAX_DNS DNS servers */
495 if (dhcp
->dns_count
> DHCP_MAX_DNS
) dhcp
->dns_count
= DHCP_MAX_DNS
;
496 for (n
= 0; n
< dhcp
->dns_count
; n
++)
498 dhcp
->offered_dns_addr
[n
].addr
= htonl(dhcp_get_option_long(&option_ptr
[2+(n
<<2)]));
504 * Start DHCP negotiation for a network interface.
506 * If no DHCP client instance was attached to this interface,
507 * a new client is created first. If a DHCP client instance
508 * was already present, it restarts negotiation.
510 * @param netif The lwIP network interface
511 * @return lwIP error code
512 * - ERR_OK - No error
513 * - ERR_MEM - Out of memory
516 err_t
dhcp_start(struct netif
*netif
)
518 struct dhcp
*dhcp
= netif
->dhcp
;
519 err_t result
= ERR_OK
;
521 LWIP_ASSERT("netif != NULL", netif
!= NULL
);
522 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| DBG_STATE
, ("dhcp_start(netif=%p) %c%c%"U16_F
"\n", (void*)netif
, netif
->name
[0], netif
->name
[1], (u16_t
)netif
->num
));
523 netif
->flags
&= ~NETIF_FLAG_DHCP
;
525 /* no DHCP client attached yet? */
527 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
, ("dhcp_start(): starting new DHCP client\n"));
528 dhcp
= mem_malloc(sizeof(struct dhcp
));
530 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
, ("dhcp_start(): could not allocate dhcp\n"));
533 /* store this dhcp client in the netif */
535 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
, ("dhcp_start(): allocated dhcp"));
536 /* already has DHCP client attached */
538 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| DBG_STATE
| 3, ("dhcp_start(): restarting DHCP configuration\n"));
541 /* clear data structure */
542 memset(dhcp
, 0, sizeof(struct dhcp
));
543 /* allocate UDP PCB */
544 dhcp
->pcb
= udp_new();
545 if (dhcp
->pcb
== NULL
) {
546 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
, ("dhcp_start(): could not obtain pcb\n"));
547 mem_free((void *)dhcp
);
548 netif
->dhcp
= dhcp
= NULL
;
551 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
, ("dhcp_start(): starting DHCP configuration\n"));
552 /* (re)start the DHCP negotiation */
553 result
= dhcp_discover(netif
);
554 if (result
!= ERR_OK
) {
555 /* free resources allocated above */
559 netif
->flags
|= NETIF_FLAG_DHCP
;
564 * Inform a DHCP server of our manual configuration.
566 * This informs DHCP servers of our fixed IP address configuration
567 * by sending an INFORM message. It does not involve DHCP address
568 * configuration, it is just here to be nice to the network.
570 * @param netif The lwIP network interface
573 void dhcp_inform(struct netif
*netif
)
576 err_t result
= ERR_OK
;
577 dhcp
= mem_malloc(sizeof(struct dhcp
));
579 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| 2, ("dhcp_inform(): could not allocate dhcp\n"));
583 memset(dhcp
, 0, sizeof(struct dhcp
));
585 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
, ("dhcp_inform(): allocated dhcp\n"));
586 dhcp
->pcb
= udp_new();
587 if (dhcp
->pcb
== NULL
) {
588 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| 2, ("dhcp_inform(): could not obtain pcb"));
589 mem_free((void *)dhcp
);
592 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
, ("dhcp_inform(): created new udp pcb\n"));
593 /* create and initialize the DHCP message header */
594 result
= dhcp_create_request(netif
);
595 if (result
== ERR_OK
) {
597 dhcp_option(dhcp
, DHCP_OPTION_MESSAGE_TYPE
, DHCP_OPTION_MESSAGE_TYPE_LEN
);
598 dhcp_option_byte(dhcp
, DHCP_INFORM
);
600 dhcp_option(dhcp
, DHCP_OPTION_MAX_MSG_SIZE
, DHCP_OPTION_MAX_MSG_SIZE_LEN
);
601 /* TODO: use netif->mtu ?! */
602 dhcp_option_short(dhcp
, 576);
604 dhcp_option_trailer(dhcp
);
606 pbuf_realloc(dhcp
->p_out
, sizeof(struct dhcp_msg
) - DHCP_OPTIONS_LEN
+ dhcp
->options_out_len
);
608 udp_bind(dhcp
->pcb
, IP_ADDR_ANY
, DHCP_CLIENT_PORT
);
609 udp_connect(dhcp
->pcb
, IP_ADDR_BROADCAST
, DHCP_SERVER_PORT
);
610 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| DBG_STATE
, ("dhcp_inform: INFORMING\n"));
611 udp_send(dhcp
->pcb
, dhcp
->p_out
);
612 udp_connect(dhcp
->pcb
, IP_ADDR_ANY
, DHCP_SERVER_PORT
);
613 dhcp_delete_request(netif
);
615 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| 2, ("dhcp_inform: could not allocate DHCP request\n"));
620 if (dhcp
->pcb
!= NULL
) udp_remove(dhcp
->pcb
);
622 mem_free((void *)dhcp
);
627 #if DHCP_DOES_ARP_CHECK
629 * Match an ARP reply with the offered IP address.
631 * @param addr The IP address we received a reply from
634 void dhcp_arp_reply(struct netif
*netif
, struct ip_addr
*addr
)
636 LWIP_ASSERT("netif != NULL", netif
!= NULL
);
637 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| 3, ("dhcp_arp_reply()\n"));
638 /* is a DHCP client doing an ARP check? */
639 if ((netif
->dhcp
!= NULL
) && (netif
->dhcp
->state
== DHCP_CHECKING
)) {
640 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| DBG_STATE
, ("dhcp_arp_reply(): CHECKING, arp reply for 0x%08"X32_F
"\n", addr
->addr
));
641 /* did a host respond with the address we
642 were offered by the DHCP server? */
643 if (ip_addr_cmp(addr
, &netif
->dhcp
->offered_ip_addr
)) {
644 /* we will not accept the offered address */
645 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| DBG_STATE
| 1, ("dhcp_arp_reply(): arp reply matched with offered address, declining\n"));
652 * Decline an offered lease.
654 * Tell the DHCP server we do not accept the offered address.
655 * One reason to decline the lease is when we find out the address
656 * is already in use by another host (through ARP).
658 static err_t
dhcp_decline(struct netif
*netif
)
660 struct dhcp
*dhcp
= netif
->dhcp
;
661 err_t result
= ERR_OK
;
663 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| 3, ("dhcp_decline()\n"));
664 dhcp_set_state(dhcp
, DHCP_BACKING_OFF
);
665 /* create and initialize the DHCP message header */
666 result
= dhcp_create_request(netif
);
667 if (result
== ERR_OK
)
669 dhcp_option(dhcp
, DHCP_OPTION_MESSAGE_TYPE
, DHCP_OPTION_MESSAGE_TYPE_LEN
);
670 dhcp_option_byte(dhcp
, DHCP_DECLINE
);
672 dhcp_option(dhcp
, DHCP_OPTION_MAX_MSG_SIZE
, DHCP_OPTION_MAX_MSG_SIZE_LEN
);
673 dhcp_option_short(dhcp
, 576);
675 dhcp_option(dhcp
, DHCP_OPTION_REQUESTED_IP
, 4);
676 dhcp_option_long(dhcp
, ntohl(dhcp
->offered_ip_addr
.addr
));
678 dhcp_option_trailer(dhcp
);
679 /* resize pbuf to reflect true size of options */
680 pbuf_realloc(dhcp
->p_out
, sizeof(struct dhcp_msg
) - DHCP_OPTIONS_LEN
+ dhcp
->options_out_len
);
682 udp_bind(dhcp
->pcb
, IP_ADDR_ANY
, DHCP_CLIENT_PORT
);
683 /* @todo: should we really connect here? we are performing sendto() */
684 udp_connect(dhcp
->pcb
, IP_ADDR_ANY
, DHCP_SERVER_PORT
);
685 /* per section 4.4.4, broadcast DECLINE messages */
686 udp_sendto(dhcp
->pcb
, dhcp
->p_out
, IP_ADDR_BROADCAST
, DHCP_SERVER_PORT
);
687 dhcp_delete_request(netif
);
688 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| DBG_STATE
, ("dhcp_decline: BACKING OFF\n"));
690 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| 2, ("dhcp_decline: could not allocate DHCP request\n"));
694 dhcp
->request_timeout
= (msecs
+ DHCP_FINE_TIMER_MSECS
- 1) / DHCP_FINE_TIMER_MSECS
;
695 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
, ("dhcp_decline(): set request timeout %"U16_F
" msecs\n", msecs
));
702 * Start the DHCP process, discover a DHCP server.
705 static err_t
dhcp_discover(struct netif
*netif
)
707 struct dhcp
*dhcp
= netif
->dhcp
;
708 err_t result
= ERR_OK
;
710 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| 3, ("dhcp_discover()\n"));
711 ip_addr_set(&dhcp
->offered_ip_addr
, IP_ADDR_ANY
);
712 /* create and initialize the DHCP message header */
713 result
= dhcp_create_request(netif
);
714 if (result
== ERR_OK
)
716 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
, ("dhcp_discover: making request\n"));
717 dhcp_option(dhcp
, DHCP_OPTION_MESSAGE_TYPE
, DHCP_OPTION_MESSAGE_TYPE_LEN
);
718 dhcp_option_byte(dhcp
, DHCP_DISCOVER
);
720 dhcp_option(dhcp
, DHCP_OPTION_MAX_MSG_SIZE
, DHCP_OPTION_MAX_MSG_SIZE_LEN
);
721 dhcp_option_short(dhcp
, 576);
723 dhcp_option(dhcp
, DHCP_OPTION_PARAMETER_REQUEST_LIST
, 4/*num options*/);
724 dhcp_option_byte(dhcp
, DHCP_OPTION_SUBNET_MASK
);
725 dhcp_option_byte(dhcp
, DHCP_OPTION_ROUTER
);
726 dhcp_option_byte(dhcp
, DHCP_OPTION_BROADCAST
);
727 dhcp_option_byte(dhcp
, DHCP_OPTION_DNS_SERVER
);
729 dhcp_option_trailer(dhcp
);
731 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
, ("dhcp_discover: realloc()ing\n"));
732 pbuf_realloc(dhcp
->p_out
, sizeof(struct dhcp_msg
) - DHCP_OPTIONS_LEN
+ dhcp
->options_out_len
);
734 /* set receive callback function with netif as user data */
735 udp_recv(dhcp
->pcb
, dhcp_recv
, netif
);
736 udp_bind(dhcp
->pcb
, IP_ADDR_ANY
, DHCP_CLIENT_PORT
);
737 udp_connect(dhcp
->pcb
, IP_ADDR_ANY
, DHCP_SERVER_PORT
);
738 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
, ("dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, DHCP_SERVER_PORT)\n"));
739 udp_sendto(dhcp
->pcb
, dhcp
->p_out
, IP_ADDR_BROADCAST
, DHCP_SERVER_PORT
);
740 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
, ("dhcp_discover: deleting()ing\n"));
741 dhcp_delete_request(netif
);
742 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| DBG_STATE
, ("dhcp_discover: SELECTING\n"));
743 dhcp_set_state(dhcp
, DHCP_SELECTING
);
745 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| 2, ("dhcp_discover: could not allocate DHCP request\n"));
748 msecs
= dhcp
->tries
< 4 ? (dhcp
->tries
+ 1) * 1000 : 10 * 1000;
749 dhcp
->request_timeout
= (msecs
+ DHCP_FINE_TIMER_MSECS
- 1) / DHCP_FINE_TIMER_MSECS
;
750 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| DBG_STATE
, ("dhcp_discover(): set request timeout %"U16_F
" msecs\n", msecs
));
756 * Bind the interface to the offered IP address.
758 * @param netif network interface to bind to the offered address
760 static void dhcp_bind(struct netif
*netif
)
762 struct dhcp
*dhcp
= netif
->dhcp
;
763 struct ip_addr sn_mask
, gw_addr
;
764 LWIP_ASSERT("dhcp_bind: netif != NULL", netif
!= NULL
);
765 LWIP_ASSERT("dhcp_bind: dhcp != NULL", dhcp
!= NULL
);
766 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| 3, ("dhcp_bind(netif=%p) %c%c%"U16_F
"\n", (void*)netif
, netif
->name
[0], netif
->name
[1], (u16_t
)netif
->num
));
768 /* temporary DHCP lease? */
769 if (dhcp
->offered_t1_renew
!= 0xffffffffUL
) {
770 /* set renewal period timer */
771 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
, ("dhcp_bind(): t1 renewal timer %"U32_F
" secs\n", dhcp
->offered_t1_renew
));
772 dhcp
->t1_timeout
= (dhcp
->offered_t1_renew
+ DHCP_COARSE_TIMER_SECS
/ 2) / DHCP_COARSE_TIMER_SECS
;
773 if (dhcp
->t1_timeout
== 0) dhcp
->t1_timeout
= 1;
774 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| DBG_STATE
, ("dhcp_bind(): set request timeout %"U32_F
" msecs\n", dhcp
->offered_t1_renew
*1000));
776 /* set renewal period timer */
777 if (dhcp
->offered_t2_rebind
!= 0xffffffffUL
) {
778 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
, ("dhcp_bind(): t2 rebind timer %"U32_F
" secs\n", dhcp
->offered_t2_rebind
));
779 dhcp
->t2_timeout
= (dhcp
->offered_t2_rebind
+ DHCP_COARSE_TIMER_SECS
/ 2) / DHCP_COARSE_TIMER_SECS
;
780 if (dhcp
->t2_timeout
== 0) dhcp
->t2_timeout
= 1;
781 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| DBG_STATE
, ("dhcp_bind(): set request timeout %"U32_F
" msecs\n", dhcp
->offered_t2_rebind
*1000));
783 /* copy offered network mask */
784 ip_addr_set(&sn_mask
, &dhcp
->offered_sn_mask
);
786 /* subnet mask not given? */
787 /* TODO: this is not a valid check. what if the network mask is 0? */
788 if (sn_mask
.addr
== 0) {
789 /* choose a safe subnet mask given the network class */
790 u8_t first_octet
= ip4_addr1(&sn_mask
);
791 if (first_octet
<= 127) sn_mask
.addr
= htonl(0xff000000);
792 else if (first_octet
>= 192) sn_mask
.addr
= htonl(0xffffff00);
793 else sn_mask
.addr
= htonl(0xffff0000);
796 ip_addr_set(&gw_addr
, &dhcp
->offered_gw_addr
);
797 /* gateway address not given? */
798 if (gw_addr
.addr
== 0) {
799 /* copy network address */
800 gw_addr
.addr
= (dhcp
->offered_ip_addr
.addr
& sn_mask
.addr
);
801 /* use first host address on network as gateway */
802 gw_addr
.addr
|= htonl(0x00000001);
805 LWIP_DEBUGF(DHCP_DEBUG
| DBG_STATE
, ("dhcp_bind(): IP: 0x%08"X32_F
"\n", dhcp
->offered_ip_addr
.addr
));
806 netif_set_ipaddr(netif
, &dhcp
->offered_ip_addr
);
807 LWIP_DEBUGF(DHCP_DEBUG
| DBG_STATE
, ("dhcp_bind(): SN: 0x%08"X32_F
"\n", sn_mask
.addr
));
808 netif_set_netmask(netif
, &sn_mask
);
809 LWIP_DEBUGF(DHCP_DEBUG
| DBG_STATE
, ("dhcp_bind(): GW: 0x%08"X32_F
"\n", gw_addr
.addr
));
810 netif_set_gw(netif
, &gw_addr
);
811 /* bring the interface up */
813 /* netif is now bound to DHCP leased address */
814 dhcp_set_state(dhcp
, DHCP_BOUND
);
818 * Renew an existing DHCP lease at the involved DHCP server.
820 * @param netif network interface which must renew its lease
822 err_t
dhcp_renew(struct netif
*netif
)
824 struct dhcp
*dhcp
= netif
->dhcp
;
827 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| 3, ("dhcp_renew()\n"));
828 dhcp_set_state(dhcp
, DHCP_RENEWING
);
830 /* create and initialize the DHCP message header */
831 result
= dhcp_create_request(netif
);
832 if (result
== ERR_OK
) {
834 dhcp_option(dhcp
, DHCP_OPTION_MESSAGE_TYPE
, DHCP_OPTION_MESSAGE_TYPE_LEN
);
835 dhcp_option_byte(dhcp
, DHCP_REQUEST
);
837 dhcp_option(dhcp
, DHCP_OPTION_MAX_MSG_SIZE
, DHCP_OPTION_MAX_MSG_SIZE_LEN
);
838 /* TODO: use netif->mtu in some way */
839 dhcp_option_short(dhcp
, 576);
842 dhcp_option(dhcp
, DHCP_OPTION_REQUESTED_IP
, 4);
843 dhcp_option_long(dhcp
, ntohl(dhcp
->offered_ip_addr
.addr
));
847 dhcp_option(dhcp
, DHCP_OPTION_SERVER_ID
, 4);
848 dhcp_option_long(dhcp
, ntohl(dhcp
->server_ip_addr
.addr
));
850 /* append DHCP message trailer */
851 dhcp_option_trailer(dhcp
);
853 pbuf_realloc(dhcp
->p_out
, sizeof(struct dhcp_msg
) - DHCP_OPTIONS_LEN
+ dhcp
->options_out_len
);
855 udp_bind(dhcp
->pcb
, IP_ADDR_ANY
, DHCP_CLIENT_PORT
);
856 udp_connect(dhcp
->pcb
, &dhcp
->server_ip_addr
, DHCP_SERVER_PORT
);
857 udp_send(dhcp
->pcb
, dhcp
->p_out
);
858 dhcp_delete_request(netif
);
860 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| DBG_STATE
, ("dhcp_renew: RENEWING\n"));
862 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| 2, ("dhcp_renew: could not allocate DHCP request\n"));
865 /* back-off on retries, but to a maximum of 20 seconds */
866 msecs
= dhcp
->tries
< 10 ? dhcp
->tries
* 2000 : 20 * 1000;
867 dhcp
->request_timeout
= (msecs
+ DHCP_FINE_TIMER_MSECS
- 1) / DHCP_FINE_TIMER_MSECS
;
868 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| DBG_STATE
, ("dhcp_renew(): set request timeout %"U16_F
" msecs\n", msecs
));
873 * Rebind with a DHCP server for an existing DHCP lease.
875 * @param netif network interface which must rebind with a DHCP server
877 static err_t
dhcp_rebind(struct netif
*netif
)
879 struct dhcp
*dhcp
= netif
->dhcp
;
882 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| DBG_STATE
, ("dhcp_rebind()\n"));
883 dhcp_set_state(dhcp
, DHCP_REBINDING
);
885 /* create and initialize the DHCP message header */
886 result
= dhcp_create_request(netif
);
887 if (result
== ERR_OK
)
890 dhcp_option(dhcp
, DHCP_OPTION_MESSAGE_TYPE
, DHCP_OPTION_MESSAGE_TYPE_LEN
);
891 dhcp_option_byte(dhcp
, DHCP_REQUEST
);
893 dhcp_option(dhcp
, DHCP_OPTION_MAX_MSG_SIZE
, DHCP_OPTION_MAX_MSG_SIZE_LEN
);
894 dhcp_option_short(dhcp
, 576);
897 dhcp_option(dhcp
, DHCP_OPTION_REQUESTED_IP
, 4);
898 dhcp_option_long(dhcp
, ntohl(dhcp
->offered_ip_addr
.addr
));
900 dhcp_option(dhcp
, DHCP_OPTION_SERVER_ID
, 4);
901 dhcp_option_long(dhcp
, ntohl(dhcp
->server_ip_addr
.addr
));
904 dhcp_option_trailer(dhcp
);
906 pbuf_realloc(dhcp
->p_out
, sizeof(struct dhcp_msg
) - DHCP_OPTIONS_LEN
+ dhcp
->options_out_len
);
908 /* set remote IP association to any DHCP server */
909 udp_bind(dhcp
->pcb
, IP_ADDR_ANY
, DHCP_CLIENT_PORT
);
910 udp_connect(dhcp
->pcb
, IP_ADDR_ANY
, DHCP_SERVER_PORT
);
911 /* broadcast to server */
912 udp_sendto(dhcp
->pcb
, dhcp
->p_out
, IP_ADDR_BROADCAST
, DHCP_SERVER_PORT
);
913 dhcp_delete_request(netif
);
914 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| DBG_STATE
, ("dhcp_rebind: REBINDING\n"));
916 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| 2, ("dhcp_rebind: could not allocate DHCP request\n"));
919 msecs
= dhcp
->tries
< 10 ? dhcp
->tries
* 1000 : 10 * 1000;
920 dhcp
->request_timeout
= (msecs
+ DHCP_FINE_TIMER_MSECS
- 1) / DHCP_FINE_TIMER_MSECS
;
921 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| DBG_STATE
, ("dhcp_rebind(): set request timeout %"U16_F
" msecs\n", msecs
));
926 * Release a DHCP lease.
928 * @param netif network interface which must release its lease
930 err_t
dhcp_release(struct netif
*netif
)
932 struct dhcp
*dhcp
= netif
->dhcp
;
935 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| 3, ("dhcp_release()\n"));
937 /* idle DHCP client */
938 dhcp_set_state(dhcp
, DHCP_OFF
);
939 /* clean old DHCP offer */
940 dhcp
->server_ip_addr
.addr
= 0;
941 dhcp
->offered_ip_addr
.addr
= dhcp
->offered_sn_mask
.addr
= 0;
942 dhcp
->offered_gw_addr
.addr
= dhcp
->offered_bc_addr
.addr
= 0;
943 dhcp
->offered_t0_lease
= dhcp
->offered_t1_renew
= dhcp
->offered_t2_rebind
= 0;
946 /* create and initialize the DHCP message header */
947 result
= dhcp_create_request(netif
);
948 if (result
== ERR_OK
) {
949 dhcp_option(dhcp
, DHCP_OPTION_MESSAGE_TYPE
, DHCP_OPTION_MESSAGE_TYPE_LEN
);
950 dhcp_option_byte(dhcp
, DHCP_RELEASE
);
952 dhcp_option_trailer(dhcp
);
954 pbuf_realloc(dhcp
->p_out
, sizeof(struct dhcp_msg
) - DHCP_OPTIONS_LEN
+ dhcp
->options_out_len
);
956 udp_bind(dhcp
->pcb
, IP_ADDR_ANY
, DHCP_CLIENT_PORT
);
957 udp_connect(dhcp
->pcb
, &dhcp
->server_ip_addr
, DHCP_SERVER_PORT
);
958 udp_send(dhcp
->pcb
, dhcp
->p_out
);
959 dhcp_delete_request(netif
);
960 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| DBG_STATE
, ("dhcp_release: RELEASED, DHCP_OFF\n"));
962 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| 2, ("dhcp_release: could not allocate DHCP request\n"));
965 msecs
= dhcp
->tries
< 10 ? dhcp
->tries
* 1000 : 10 * 1000;
966 dhcp
->request_timeout
= (msecs
+ DHCP_FINE_TIMER_MSECS
- 1) / DHCP_FINE_TIMER_MSECS
;
967 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| DBG_STATE
, ("dhcp_release(): set request timeout %"U16_F
" msecs\n", msecs
));
968 /* bring the interface down */
969 netif_set_down(netif
);
970 /* remove IP address from interface */
971 netif_set_ipaddr(netif
, IP_ADDR_ANY
);
972 netif_set_gw(netif
, IP_ADDR_ANY
);
973 netif_set_netmask(netif
, IP_ADDR_ANY
);
975 /* TODO: netif_down(netif); */
979 * Remove the DHCP client from the interface.
981 * @param netif The network interface to stop DHCP on
983 void dhcp_stop(struct netif
*netif
)
985 struct dhcp
*dhcp
= netif
->dhcp
;
986 LWIP_ASSERT("dhcp_stop: netif != NULL", netif
!= NULL
);
988 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| 3, ("dhcp_stop()\n"));
989 /* netif is DHCP configured? */
992 if (dhcp
->pcb
!= NULL
)
994 udp_remove(dhcp
->pcb
);
1002 /* free unfolded reply */
1003 dhcp_free_reply(dhcp
);
1004 mem_free((void *)dhcp
);
1010 * Set the DHCP state of a DHCP client.
1012 * If the state changed, reset the number of tries.
1014 * TODO: we might also want to reset the timeout here?
1016 static void dhcp_set_state(struct dhcp
*dhcp
, u8_t new_state
)
1018 if (new_state
!= dhcp
->state
)
1020 dhcp
->state
= new_state
;
1026 * Concatenate an option type and length field to the outgoing
1030 static void dhcp_option(struct dhcp
*dhcp
, u8_t option_type
, u8_t option_len
)
1032 LWIP_ASSERT("dhcp_option_short: dhcp->options_out_len + 2 + option_len <= DHCP_OPTIONS_LEN", dhcp
->options_out_len
+ 2 + option_len
<= DHCP_OPTIONS_LEN
);
1033 dhcp
->msg_out
->options
[dhcp
->options_out_len
++] = option_type
;
1034 dhcp
->msg_out
->options
[dhcp
->options_out_len
++] = option_len
;
1037 * Concatenate a single byte to the outgoing DHCP message.
1040 static void dhcp_option_byte(struct dhcp
*dhcp
, u8_t value
)
1042 LWIP_ASSERT("dhcp_option_short: dhcp->options_out_len < DHCP_OPTIONS_LEN", dhcp
->options_out_len
< DHCP_OPTIONS_LEN
);
1043 dhcp
->msg_out
->options
[dhcp
->options_out_len
++] = value
;
1045 static void dhcp_option_short(struct dhcp
*dhcp
, u16_t value
)
1047 LWIP_ASSERT("dhcp_option_short: dhcp->options_out_len + 2 <= DHCP_OPTIONS_LEN", dhcp
->options_out_len
+ 2 <= DHCP_OPTIONS_LEN
);
1048 dhcp
->msg_out
->options
[dhcp
->options_out_len
++] = (value
& 0xff00U
) >> 8;
1049 dhcp
->msg_out
->options
[dhcp
->options_out_len
++] = value
& 0x00ffU
;
1051 static void dhcp_option_long(struct dhcp
*dhcp
, u32_t value
)
1053 LWIP_ASSERT("dhcp_option_long: dhcp->options_out_len + 4 <= DHCP_OPTIONS_LEN", dhcp
->options_out_len
+ 4 <= DHCP_OPTIONS_LEN
);
1054 dhcp
->msg_out
->options
[dhcp
->options_out_len
++] = (value
& 0xff000000UL
) >> 24;
1055 dhcp
->msg_out
->options
[dhcp
->options_out_len
++] = (value
& 0x00ff0000UL
) >> 16;
1056 dhcp
->msg_out
->options
[dhcp
->options_out_len
++] = (value
& 0x0000ff00UL
) >> 8;
1057 dhcp
->msg_out
->options
[dhcp
->options_out_len
++] = (value
& 0x000000ffUL
);
1061 * Extract the DHCP message and the DHCP options.
1063 * Extract the DHCP message and the DHCP options, each into a contiguous
1064 * piece of memory. As a DHCP message is variable sized by its options,
1065 * and also allows overriding some fields for options, the easy approach
1066 * is to first unfold the options into a conitguous piece of memory, and
1067 * use that further on.
1070 static err_t
dhcp_unfold_reply(struct dhcp
*dhcp
)
1072 struct pbuf
*p
= dhcp
->p
;
1076 LWIP_ASSERT("dhcp->p != NULL", dhcp
->p
!= NULL
);
1077 /* free any left-overs from previous unfolds */
1078 dhcp_free_reply(dhcp
);
1079 /* options present? */
1080 if (dhcp
->p
->tot_len
> (sizeof(struct dhcp_msg
) - DHCP_OPTIONS_LEN
))
1082 dhcp
->options_in_len
= dhcp
->p
->tot_len
- (sizeof(struct dhcp_msg
) - DHCP_OPTIONS_LEN
);
1083 dhcp
->options_in
= mem_malloc(dhcp
->options_in_len
);
1084 if (dhcp
->options_in
== NULL
)
1086 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| 2, ("dhcp_unfold_reply(): could not allocate dhcp->options\n"));
1090 dhcp
->msg_in
= mem_malloc(sizeof(struct dhcp_msg
) - DHCP_OPTIONS_LEN
);
1091 if (dhcp
->msg_in
== NULL
)
1093 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| 2, ("dhcp_unfold_reply(): could not allocate dhcp->msg_in\n"));
1094 mem_free((void *)dhcp
->options_in
);
1095 dhcp
->options_in
= NULL
;
1099 ptr
= (u8_t
*)dhcp
->msg_in
;
1100 /* proceed through struct dhcp_msg */
1101 for (i
= 0; i
< sizeof(struct dhcp_msg
) - DHCP_OPTIONS_LEN
; i
++)
1103 *ptr
++ = ((u8_t
*)p
->payload
)[j
++];
1104 /* reached end of pbuf? */
1107 /* proceed to next pbuf in chain */
1112 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
, ("dhcp_unfold_reply(): copied %"U16_F
" bytes into dhcp->msg_in[]\n", i
));
1113 if (dhcp
->options_in
!= NULL
) {
1114 ptr
= (u8_t
*)dhcp
->options_in
;
1115 /* proceed through options */
1116 for (i
= 0; i
< dhcp
->options_in_len
; i
++) {
1117 *ptr
++ = ((u8_t
*)p
->payload
)[j
++];
1118 /* reached end of pbuf? */
1120 /* proceed to next pbuf in chain */
1125 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
, ("dhcp_unfold_reply(): copied %"U16_F
" bytes to dhcp->options_in[]\n", i
));
1131 * Free the incoming DHCP message including contiguous copy of
1135 static void dhcp_free_reply(struct dhcp
*dhcp
)
1137 if (dhcp
->msg_in
!= NULL
) {
1138 mem_free((void *)dhcp
->msg_in
);
1139 dhcp
->msg_in
= NULL
;
1141 if (dhcp
->options_in
) {
1142 mem_free((void *)dhcp
->options_in
);
1143 dhcp
->options_in
= NULL
;
1144 dhcp
->options_in_len
= 0;
1146 LWIP_DEBUGF(DHCP_DEBUG
, ("dhcp_free_reply(): free'd\n"));
1151 * If an incoming DHCP message is in response to us, then trigger the state machine
1153 static void dhcp_recv(void *arg
, struct udp_pcb
*pcb
, struct pbuf
*p
, struct ip_addr
*addr
, u16_t port
)
1155 struct netif
*netif
= (struct netif
*)arg
;
1156 struct dhcp
*dhcp
= netif
->dhcp
;
1157 struct dhcp_msg
*reply_msg
= (struct dhcp_msg
*)p
->payload
;
1161 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| 3, ("dhcp_recv(pbuf = %p) from DHCP server %"U16_F
".%"U16_F
".%"U16_F
".%"U16_F
" port %"U16_F
"\n", (void*)p
,
1162 (u16_t
)(ntohl(addr
->addr
) >> 24 & 0xff), (u16_t
)(ntohl(addr
->addr
) >> 16 & 0xff),
1163 (u16_t
)(ntohl(addr
->addr
) >> 8 & 0xff), (u16_t
)(ntohl(addr
->addr
) & 0xff), port
));
1164 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
, ("pbuf->len = %"U16_F
"\n", p
->len
));
1165 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
, ("pbuf->tot_len = %"U16_F
"\n", p
->tot_len
));
1166 /* prevent warnings about unused arguments */
1167 (void)pcb
; (void)addr
; (void)port
;
1169 /* TODO: check packet length before reading them */
1170 if (reply_msg
->op
!= DHCP_BOOTREPLY
) {
1171 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| 1, ("not a DHCP reply message, but type %"U16_F
"\n", (u16_t
)reply_msg
->op
));
1176 /* iterate through hardware address and match against DHCP message */
1177 for (i
= 0; i
< netif
->hwaddr_len
; i
++) {
1178 if (netif
->hwaddr
[i
] != reply_msg
->chaddr
[i
]) {
1179 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| 2, ("netif->hwaddr[%"U16_F
"]==%02"X16_F
" != reply_msg->chaddr[%"U16_F
"]==%02"X16_F
"\n",
1180 (u16_t
)i
, (u16_t
)netif
->hwaddr
[i
], (u16_t
)i
, (u16_t
)reply_msg
->chaddr
[i
]));
1186 /* match transaction ID against what we expected */
1187 if (ntohl(reply_msg
->xid
) != dhcp
->xid
) {
1188 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| 2, ("transaction id mismatch\n"));
1193 /* option fields could be unfold? */
1194 if (dhcp_unfold_reply(dhcp
) != ERR_OK
) {
1195 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| 2, ("problem unfolding DHCP message - too short on memory?\n"));
1201 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
, ("searching DHCP_OPTION_MESSAGE_TYPE\n"));
1202 /* obtain pointer to DHCP message type */
1203 options_ptr
= dhcp_get_option_ptr(dhcp
, DHCP_OPTION_MESSAGE_TYPE
);
1204 if (options_ptr
== NULL
) {
1205 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| 1, ("DHCP_OPTION_MESSAGE_TYPE option not found\n"));
1211 /* read DHCP message type */
1212 msg_type
= dhcp_get_option_byte(options_ptr
+ 2);
1213 /* message type is DHCP ACK? */
1214 if (msg_type
== DHCP_ACK
) {
1215 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| 1, ("DHCP_ACK received\n"));
1216 /* in requesting state? */
1217 if (dhcp
->state
== DHCP_REQUESTING
) {
1218 dhcp_handle_ack(netif
);
1219 dhcp
->request_timeout
= 0;
1220 #if DHCP_DOES_ARP_CHECK
1221 /* check if the acknowledged lease address is already in use */
1224 /* bind interface to the acknowledged lease address */
1228 /* already bound to the given lease address? */
1229 else if ((dhcp
->state
== DHCP_REBOOTING
) || (dhcp
->state
== DHCP_REBINDING
) || (dhcp
->state
== DHCP_RENEWING
)) {
1230 dhcp
->request_timeout
= 0;
1234 /* received a DHCP_NAK in appropriate state? */
1235 else if ((msg_type
== DHCP_NAK
) &&
1236 ((dhcp
->state
== DHCP_REBOOTING
) || (dhcp
->state
== DHCP_REQUESTING
) ||
1237 (dhcp
->state
== DHCP_REBINDING
) || (dhcp
->state
== DHCP_RENEWING
))) {
1238 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| 1, ("DHCP_NAK received\n"));
1239 dhcp
->request_timeout
= 0;
1240 dhcp_handle_nak(netif
);
1242 /* received a DHCP_OFFER in DHCP_SELECTING state? */
1243 else if ((msg_type
== DHCP_OFFER
) && (dhcp
->state
== DHCP_SELECTING
)) {
1244 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| 1, ("DHCP_OFFER received in DHCP_SELECTING state\n"));
1245 dhcp
->request_timeout
= 0;
1246 /* remember offered lease */
1247 dhcp_handle_offer(netif
);
1254 static err_t
dhcp_create_request(struct netif
*netif
)
1256 struct dhcp
*dhcp
= netif
->dhcp
;
1258 LWIP_ASSERT("dhcp_create_request: dhcp->p_out == NULL", dhcp
->p_out
== NULL
);
1259 LWIP_ASSERT("dhcp_create_request: dhcp->msg_out == NULL", dhcp
->msg_out
== NULL
);
1260 dhcp
->p_out
= pbuf_alloc(PBUF_TRANSPORT
, sizeof(struct dhcp_msg
), PBUF_RAM
);
1261 if (dhcp
->p_out
== NULL
) {
1262 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| 2, ("dhcp_create_request(): could not allocate pbuf\n"));
1265 /* give unique transaction identifier to this request */
1268 dhcp
->msg_out
= (struct dhcp_msg
*)dhcp
->p_out
->payload
;
1270 dhcp
->msg_out
->op
= DHCP_BOOTREQUEST
;
1271 /* TODO: make link layer independent */
1272 dhcp
->msg_out
->htype
= DHCP_HTYPE_ETH
;
1273 /* TODO: make link layer independent */
1274 dhcp
->msg_out
->hlen
= DHCP_HLEN_ETH
;
1275 dhcp
->msg_out
->hops
= 0;
1276 dhcp
->msg_out
->xid
= htonl(dhcp
->xid
);
1277 dhcp
->msg_out
->secs
= 0;
1278 dhcp
->msg_out
->flags
= 0;
1279 dhcp
->msg_out
->ciaddr
.addr
= netif
->ip_addr
.addr
;
1280 dhcp
->msg_out
->yiaddr
.addr
= 0;
1281 dhcp
->msg_out
->siaddr
.addr
= 0;
1282 dhcp
->msg_out
->giaddr
.addr
= 0;
1283 for (i
= 0; i
< DHCP_CHADDR_LEN
; i
++) {
1284 /* copy netif hardware address, pad with zeroes */
1285 dhcp
->msg_out
->chaddr
[i
] = (i
< netif
->hwaddr_len
) ? netif
->hwaddr
[i
] : 0/* pad byte*/;
1287 for (i
= 0; i
< DHCP_SNAME_LEN
; i
++) dhcp
->msg_out
->sname
[i
] = 0;
1288 for (i
= 0; i
< DHCP_FILE_LEN
; i
++) dhcp
->msg_out
->file
[i
] = 0;
1289 dhcp
->msg_out
->cookie
= htonl(0x63825363UL
);
1290 dhcp
->options_out_len
= 0;
1291 /* fill options field with an incrementing array (for debugging purposes) */
1292 for (i
= 0; i
< DHCP_OPTIONS_LEN
; i
++) dhcp
->msg_out
->options
[i
] = i
;
1296 static void dhcp_delete_request(struct netif
*netif
)
1298 struct dhcp
*dhcp
= netif
->dhcp
;
1299 LWIP_ASSERT("dhcp_free_msg: dhcp->p_out != NULL", dhcp
->p_out
!= NULL
);
1300 LWIP_ASSERT("dhcp_free_msg: dhcp->msg_out != NULL", dhcp
->msg_out
!= NULL
);
1301 pbuf_free(dhcp
->p_out
);
1303 dhcp
->msg_out
= NULL
;
1307 * Add a DHCP message trailer
1309 * Adds the END option to the DHCP message, and if
1310 * necessary, up to three padding bytes.
1313 static void dhcp_option_trailer(struct dhcp
*dhcp
)
1315 LWIP_ASSERT("dhcp_option_trailer: dhcp->msg_out != NULL\n", dhcp
->msg_out
!= NULL
);
1316 LWIP_ASSERT("dhcp_option_trailer: dhcp->options_out_len < DHCP_OPTIONS_LEN\n", dhcp
->options_out_len
< DHCP_OPTIONS_LEN
);
1317 dhcp
->msg_out
->options
[dhcp
->options_out_len
++] = DHCP_OPTION_END
;
1318 /* packet is too small, or not 4 byte aligned? */
1319 while ((dhcp
->options_out_len
< DHCP_MIN_OPTIONS_LEN
) || (dhcp
->options_out_len
& 3)) {
1320 /* LWIP_DEBUGF(DHCP_DEBUG,("dhcp_option_trailer:dhcp->options_out_len=%"U16_F", DHCP_OPTIONS_LEN=%"U16_F, dhcp->options_out_len, DHCP_OPTIONS_LEN)); */
1321 LWIP_ASSERT("dhcp_option_trailer: dhcp->options_out_len < DHCP_OPTIONS_LEN\n", dhcp
->options_out_len
< DHCP_OPTIONS_LEN
);
1322 /* add a fill/padding byte */
1323 dhcp
->msg_out
->options
[dhcp
->options_out_len
++] = 0;
1328 * Find the offset of a DHCP option inside the DHCP message.
1330 * @param client DHCP client
1331 * @param option_type
1333 * @return a byte offset into the UDP message where the option was found, or
1334 * zero if the given option was not found.
1336 static u8_t
*dhcp_get_option_ptr(struct dhcp
*dhcp
, u8_t option_type
)
1338 u8_t overload
= DHCP_OVERLOAD_NONE
;
1340 /* options available? */
1341 if ((dhcp
->options_in
!= NULL
) && (dhcp
->options_in_len
> 0)) {
1342 /* start with options field */
1343 u8_t
*options
= (u8_t
*)dhcp
->options_in
;
1345 /* at least 1 byte to read and no end marker, then at least 3 bytes to read? */
1346 while ((offset
< dhcp
->options_in_len
) && (options
[offset
] != DHCP_OPTION_END
)) {
1347 /* LWIP_DEBUGF(DHCP_DEBUG, ("msg_offset=%"U16_F", q->len=%"U16_F, msg_offset, q->len)); */
1348 /* are the sname and/or file field overloaded with options? */
1349 if (options
[offset
] == DHCP_OPTION_OVERLOAD
) {
1350 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| 2, ("overloaded message detected\n"));
1351 /* skip option type and length */
1353 overload
= options
[offset
++];
1355 /* requested option found */
1356 else if (options
[offset
] == option_type
) {
1357 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
, ("option found at offset %"U16_F
" in options\n", offset
));
1358 return &options
[offset
];
1361 LWIP_DEBUGF(DHCP_DEBUG
, ("skipping option %"U16_F
" in options\n", options
[offset
]));
1362 /* skip option type */
1364 /* skip option length, and then length bytes */
1365 offset
+= 1 + options
[offset
];
1368 /* is this an overloaded message? */
1369 if (overload
!= DHCP_OVERLOAD_NONE
) {
1371 if (overload
== DHCP_OVERLOAD_FILE
) {
1372 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| 1, ("overloaded file field\n"));
1373 options
= (u8_t
*)&dhcp
->msg_in
->file
;
1374 field_len
= DHCP_FILE_LEN
;
1375 } else if (overload
== DHCP_OVERLOAD_SNAME
) {
1376 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| 1, ("overloaded sname field\n"));
1377 options
= (u8_t
*)&dhcp
->msg_in
->sname
;
1378 field_len
= DHCP_SNAME_LEN
;
1379 /* TODO: check if else if () is necessary */
1381 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
| 1, ("overloaded sname and file field\n"));
1382 options
= (u8_t
*)&dhcp
->msg_in
->sname
;
1383 field_len
= DHCP_FILE_LEN
+ DHCP_SNAME_LEN
;
1387 /* at least 1 byte to read and no end marker */
1388 while ((offset
< field_len
) && (options
[offset
] != DHCP_OPTION_END
)) {
1389 if (options
[offset
] == option_type
) {
1390 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
, ("option found at offset=%"U16_F
"\n", offset
));
1391 return &options
[offset
];
1394 LWIP_DEBUGF(DHCP_DEBUG
| DBG_TRACE
, ("skipping option %"U16_F
"\n", options
[offset
]));
1395 /* skip option type */
1397 offset
+= 1 + options
[offset
];
1406 * Return the byte of DHCP option data.
1408 * @param client DHCP client.
1409 * @param ptr pointer obtained by dhcp_get_option_ptr().
1411 * @return byte value at the given address.
1413 static u8_t
dhcp_get_option_byte(u8_t
*ptr
)
1415 LWIP_DEBUGF(DHCP_DEBUG
, ("option byte value=%"U16_F
"\n", (u16_t
)(*ptr
)));
1420 * Return the 16-bit value of DHCP option data.
1422 * @param client DHCP client.
1423 * @param ptr pointer obtained by dhcp_get_option_ptr().
1425 * @return byte value at the given address.
1428 static u16_t
dhcp_get_option_short(u8_t
*ptr
)
1431 value
= *ptr
++ << 8;
1433 LWIP_DEBUGF(DHCP_DEBUG
, ("option short value=%"U16_F
"\n", value
));
1439 * Return the 32-bit value of DHCP option data.
1441 * @param client DHCP client.
1442 * @param ptr pointer obtained by dhcp_get_option_ptr().
1444 * @return byte value at the given address.
1446 static u32_t
dhcp_get_option_long(u8_t
*ptr
)
1449 value
= (u32_t
)(*ptr
++) << 24;
1450 value
|= (u32_t
)(*ptr
++) << 16;
1451 value
|= (u32_t
)(*ptr
++) << 8;
1452 value
|= (u32_t
)(*ptr
++);
1453 LWIP_DEBUGF(DHCP_DEBUG
, ("option long value=%"U32_F
"\n", value
));
1457 #endif /* LWIP_DHCP */