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, unsigned char 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%u\n", netif,
148 netif->name[0], netif->name[1], (unsigned int)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 %u 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, (unsigned int)netif->name[0],
167 (unsigned int)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 %u 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%u\n", netif,
192 netif->name[0], netif->name[1], 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%08lx\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%08lx\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%u\n", netif, netif->name[0], netif->name[1], 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 %u 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%u\n", netif, netif->name[0], netif->name[1], 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_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_arp_reply()\n"));
637 /* is this DHCP client doing an ARP check? */
638 if ((netif->dhcp != NULL) && (netif->dhcp->state == DHCP_CHECKING)) {
639 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_arp_reply(): CHECKING, arp reply for 0x%08lx\n", addr->addr));
640 /* did a host respond with the address we
641 were offered by the DHCP server? */
642 if (ip_addr_cmp(addr, &netif->dhcp->offered_ip_addr)) {
643 /* we will not accept the offered address */
644 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE | 1, ("dhcp_arp_reply(): arp reply matched with offered address, declining\n"));
651 * Decline an offered lease.
653 * Tell the DHCP server we do not accept the offered address.
654 * One reason to decline the lease is when we find out the address
655 * is already in use by another host (through ARP).
657 static err_t dhcp_decline(struct netif *netif)
659 struct dhcp *dhcp = netif->dhcp;
660 err_t result = ERR_OK;
662 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_decline()\n"));
663 dhcp_set_state(dhcp, DHCP_BACKING_OFF);
664 /* create and initialize the DHCP message header */
665 result = dhcp_create_request(netif);
666 if (result == ERR_OK)
668 dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
669 dhcp_option_byte(dhcp, DHCP_DECLINE);
671 dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
672 dhcp_option_short(dhcp, 576);
674 dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
675 dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr));
677 dhcp_option_trailer(dhcp);
678 /* resize pbuf to reflect true size of options */
679 pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
681 udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
682 /* @todo: should we really connect here? we are performing sendto() */
683 udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
684 /* per section 4.4.4, broadcast DECLINE messages */
685 udp_sendto(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT);
686 dhcp_delete_request(netif);
687 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_decline: BACKING OFF\n"));
689 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("dhcp_decline: could not allocate DHCP request\n"));
693 dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
694 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_decline(): set request timeout %u msecs\n", msecs));
701 * Start the DHCP process, discover a DHCP server.
704 static err_t dhcp_discover(struct netif *netif)
706 struct dhcp *dhcp = netif->dhcp;
707 err_t result = ERR_OK;
709 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_discover()\n"));
710 ip_addr_set(&dhcp->offered_ip_addr, IP_ADDR_ANY);
711 /* create and initialize the DHCP message header */
712 result = dhcp_create_request(netif);
713 if (result == ERR_OK)
715 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_discover: making request\n"));
716 dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
717 dhcp_option_byte(dhcp, DHCP_DISCOVER);
719 dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
720 dhcp_option_short(dhcp, 576);
722 dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 4/*num options*/);
723 dhcp_option_byte(dhcp, DHCP_OPTION_SUBNET_MASK);
724 dhcp_option_byte(dhcp, DHCP_OPTION_ROUTER);
725 dhcp_option_byte(dhcp, DHCP_OPTION_BROADCAST);
726 dhcp_option_byte(dhcp, DHCP_OPTION_DNS_SERVER);
728 dhcp_option_trailer(dhcp);
730 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_discover: realloc()ing\n"));
731 pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
733 /* set receive callback function with netif as user data */
734 udp_recv(dhcp->pcb, dhcp_recv, netif);
735 udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
736 udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
737 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, DHCP_SERVER_PORT)\n"));
738 udp_sendto(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT);
739 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_discover: deleting()ing\n"));
740 dhcp_delete_request(netif);
741 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_discover: SELECTING\n"));
742 dhcp_set_state(dhcp, DHCP_SELECTING);
744 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("dhcp_discover: could not allocate DHCP request\n"));
747 msecs = dhcp->tries < 4 ? (dhcp->tries + 1) * 1000 : 10 * 1000;
748 dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
749 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_discover(): set request timeout %u msecs\n", msecs));
755 * Bind the interface to the offered IP address.
757 * @param netif network interface to bind to the offered address
759 static void dhcp_bind(struct netif *netif)
761 struct dhcp *dhcp = netif->dhcp;
762 struct ip_addr sn_mask, gw_addr;
763 LWIP_ASSERT("dhcp_bind: netif != NULL", netif != NULL);
764 LWIP_ASSERT("dhcp_bind: dhcp != NULL", dhcp != NULL);
765 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_bind(netif=%p) %c%c%u\n", netif, netif->name[0], netif->name[1], netif->num));
767 /* temporary DHCP lease? */
768 if (dhcp->offered_t1_renew != 0xffffffffUL) {
769 /* set renewal period timer */
770 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_bind(): t1 renewal timer %lu secs\n", dhcp->offered_t1_renew));
771 dhcp->t1_timeout = (dhcp->offered_t1_renew + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS;
772 if (dhcp->t1_timeout == 0) dhcp->t1_timeout = 1;
773 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_bind(): set request timeout %u msecs\n", dhcp->offered_t1_renew*1000));
775 /* set renewal period timer */
776 if (dhcp->offered_t2_rebind != 0xffffffffUL) {
777 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_bind(): t2 rebind timer %lu secs\n", dhcp->offered_t2_rebind));
778 dhcp->t2_timeout = (dhcp->offered_t2_rebind + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS;
779 if (dhcp->t2_timeout == 0) dhcp->t2_timeout = 1;
780 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_bind(): set request timeout %u msecs\n", dhcp->offered_t2_rebind*1000));
782 /* copy offered network mask */
783 ip_addr_set(&sn_mask, &dhcp->offered_sn_mask);
785 /* subnet mask not given? */
786 /* TODO: this is not a valid check. what if the network mask is 0? */
787 if (sn_mask.addr == 0) {
788 /* choose a safe subnet mask given the network class */
789 u8_t first_octet = ip4_addr1(&sn_mask);
790 if (first_octet <= 127) sn_mask.addr = htonl(0xff000000);
791 else if (first_octet >= 192) sn_mask.addr = htonl(0xffffff00);
792 else sn_mask.addr = htonl(0xffff0000);
795 ip_addr_set(&gw_addr, &dhcp->offered_gw_addr);
796 /* gateway address not given? */
797 if (gw_addr.addr == 0) {
798 /* copy network address */
799 gw_addr.addr = (dhcp->offered_ip_addr.addr & sn_mask.addr);
800 /* use first host address on network as gateway */
801 gw_addr.addr |= htonl(0x00000001);
804 LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_bind(): IP: 0x%08lx\n", dhcp->offered_ip_addr.addr));
805 netif_set_ipaddr(netif, &dhcp->offered_ip_addr);
806 LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_bind(): SN: 0x%08lx\n", sn_mask.addr));
807 netif_set_netmask(netif, &sn_mask);
808 LWIP_DEBUGF(DHCP_DEBUG | DBG_STATE, ("dhcp_bind(): GW: 0x%08lx\n", gw_addr.addr));
809 netif_set_gw(netif, &gw_addr);
810 /* bring the interface up */
812 /* netif is now bound to DHCP leased address */
813 dhcp_set_state(dhcp, DHCP_BOUND);
817 * Renew an existing DHCP lease at the involved DHCP server.
819 * @param netif network interface which must renew its lease
821 err_t dhcp_renew(struct netif *netif)
823 struct dhcp *dhcp = netif->dhcp;
826 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_renew()\n"));
827 dhcp_set_state(dhcp, DHCP_RENEWING);
829 /* create and initialize the DHCP message header */
830 result = dhcp_create_request(netif);
831 if (result == ERR_OK) {
833 dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
834 dhcp_option_byte(dhcp, DHCP_REQUEST);
836 dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
837 /* TODO: use netif->mtu in some way */
838 dhcp_option_short(dhcp, 576);
841 dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
842 dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr));
846 dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4);
847 dhcp_option_long(dhcp, ntohl(dhcp->server_ip_addr.addr));
849 /* append DHCP message trailer */
850 dhcp_option_trailer(dhcp);
852 pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
854 udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
855 udp_connect(dhcp->pcb, &dhcp->server_ip_addr, DHCP_SERVER_PORT);
856 udp_send(dhcp->pcb, dhcp->p_out);
857 dhcp_delete_request(netif);
859 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_renew: RENEWING\n"));
861 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("dhcp_renew: could not allocate DHCP request\n"));
864 /* back-off on retries, but to a maximum of 20 seconds */
865 msecs = dhcp->tries < 10 ? dhcp->tries * 2000 : 20 * 1000;
866 dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
867 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_renew(): set request timeout %u msecs\n", msecs));
872 * Rebind with a DHCP server for an existing DHCP lease.
874 * @param netif network interface which must rebind with a DHCP server
876 static err_t dhcp_rebind(struct netif *netif)
878 struct dhcp *dhcp = netif->dhcp;
881 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_rebind()\n"));
882 dhcp_set_state(dhcp, DHCP_REBINDING);
884 /* create and initialize the DHCP message header */
885 result = dhcp_create_request(netif);
886 if (result == ERR_OK)
889 dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
890 dhcp_option_byte(dhcp, DHCP_REQUEST);
892 dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
893 dhcp_option_short(dhcp, 576);
896 dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4);
897 dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr));
899 dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4);
900 dhcp_option_long(dhcp, ntohl(dhcp->server_ip_addr.addr));
903 dhcp_option_trailer(dhcp);
905 pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
907 /* set remote IP association to any DHCP server */
908 udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
909 udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
910 /* broadcast to server */
911 udp_sendto(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT);
912 dhcp_delete_request(netif);
913 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_rebind: REBINDING\n"));
915 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("dhcp_rebind: could not allocate DHCP request\n"));
918 msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000;
919 dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
920 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_rebind(): set request timeout %u msecs\n", msecs));
925 * Release a DHCP lease.
927 * @param netif network interface which must release its lease
929 err_t dhcp_release(struct netif *netif)
931 struct dhcp *dhcp = netif->dhcp;
934 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_release()\n"));
936 /* idle DHCP client */
937 dhcp_set_state(dhcp, DHCP_OFF);
938 /* clean old DHCP offer */
939 dhcp->server_ip_addr.addr = 0;
940 dhcp->offered_ip_addr.addr = dhcp->offered_sn_mask.addr = 0;
941 dhcp->offered_gw_addr.addr = dhcp->offered_bc_addr.addr = 0;
942 dhcp->offered_t0_lease = dhcp->offered_t1_renew = dhcp->offered_t2_rebind = 0;
945 /* create and initialize the DHCP message header */
946 result = dhcp_create_request(netif);
947 if (result == ERR_OK) {
948 dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
949 dhcp_option_byte(dhcp, DHCP_RELEASE);
951 dhcp_option_trailer(dhcp);
953 pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
955 udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
956 udp_connect(dhcp->pcb, &dhcp->server_ip_addr, DHCP_SERVER_PORT);
957 udp_send(dhcp->pcb, dhcp->p_out);
958 dhcp_delete_request(netif);
959 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_release: RELEASED, DHCP_OFF\n"));
961 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("dhcp_release: could not allocate DHCP request\n"));
964 msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000;
965 dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
966 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | DBG_STATE, ("dhcp_release(): set request timeout %u msecs\n", msecs));
967 /* bring the interface down */
968 netif_set_down(netif);
969 /* remove IP address from interface */
970 netif_set_ipaddr(netif, IP_ADDR_ANY);
971 netif_set_gw(netif, IP_ADDR_ANY);
972 netif_set_netmask(netif, IP_ADDR_ANY);
974 /* TODO: netif_down(netif); */
978 * Remove the DHCP client from the interface.
980 * @param netif The network interface to stop DHCP on
982 void dhcp_stop(struct netif *netif)
984 struct dhcp *dhcp = netif->dhcp;
985 LWIP_ASSERT("dhcp_stop: netif != NULL", netif != NULL);
987 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_stop()\n"));
988 /* netif is DHCP configured? */
991 if (dhcp->pcb != NULL)
993 udp_remove(dhcp->pcb);
1001 /* free unfolded reply */
1002 dhcp_free_reply(dhcp);
1003 mem_free((void *)dhcp);
1009 * Set the DHCP state of a DHCP client.
1011 * If the state changed, reset the number of tries.
1013 * TODO: we might also want to reset the timeout here?
1015 static void dhcp_set_state(struct dhcp *dhcp, unsigned char new_state)
1017 if (new_state != dhcp->state)
1019 dhcp->state = new_state;
1025 * Concatenate an option type and length field to the outgoing
1029 static void dhcp_option(struct dhcp *dhcp, u8_t option_type, u8_t option_len)
1031 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);
1032 dhcp->msg_out->options[dhcp->options_out_len++] = option_type;
1033 dhcp->msg_out->options[dhcp->options_out_len++] = option_len;
1036 * Concatenate a single byte to the outgoing DHCP message.
1039 static void dhcp_option_byte(struct dhcp *dhcp, u8_t value)
1041 LWIP_ASSERT("dhcp_option_short: dhcp->options_out_len < DHCP_OPTIONS_LEN", dhcp->options_out_len < DHCP_OPTIONS_LEN);
1042 dhcp->msg_out->options[dhcp->options_out_len++] = value;
1044 static void dhcp_option_short(struct dhcp *dhcp, u16_t value)
1046 LWIP_ASSERT("dhcp_option_short: dhcp->options_out_len + 2 <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 2 <= DHCP_OPTIONS_LEN);
1047 dhcp->msg_out->options[dhcp->options_out_len++] = (value & 0xff00U) >> 8;
1048 dhcp->msg_out->options[dhcp->options_out_len++] = value & 0x00ffU;
1050 static void dhcp_option_long(struct dhcp *dhcp, u32_t value)
1052 LWIP_ASSERT("dhcp_option_long: dhcp->options_out_len + 4 <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 4 <= DHCP_OPTIONS_LEN);
1053 dhcp->msg_out->options[dhcp->options_out_len++] = (value & 0xff000000UL) >> 24;
1054 dhcp->msg_out->options[dhcp->options_out_len++] = (value & 0x00ff0000UL) >> 16;
1055 dhcp->msg_out->options[dhcp->options_out_len++] = (value & 0x0000ff00UL) >> 8;
1056 dhcp->msg_out->options[dhcp->options_out_len++] = (value & 0x000000ffUL);
1060 * Extract the DHCP message and the DHCP options.
1062 * Extract the DHCP message and the DHCP options, each into a contiguous
1063 * piece of memory. As a DHCP message is variable sized by its options,
1064 * and also allows overriding some fields for options, the easy approach
1065 * is to first unfold the options into a conitguous piece of memory, and
1066 * use that further on.
1069 static err_t dhcp_unfold_reply(struct dhcp *dhcp)
1071 struct pbuf *p = dhcp->p;
1075 LWIP_ASSERT("dhcp->p != NULL", dhcp->p != NULL);
1076 /* free any left-overs from previous unfolds */
1077 dhcp_free_reply(dhcp);
1078 /* options present? */
1079 if (dhcp->p->tot_len > (sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN))
1081 dhcp->options_in_len = dhcp->p->tot_len - (sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN);
1082 dhcp->options_in = mem_malloc(dhcp->options_in_len);
1083 if (dhcp->options_in == NULL)
1085 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("dhcp_unfold_reply(): could not allocate dhcp->options\n"));
1089 dhcp->msg_in = mem_malloc(sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN);
1090 if (dhcp->msg_in == NULL)
1092 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("dhcp_unfold_reply(): could not allocate dhcp->msg_in\n"));
1093 mem_free((void *)dhcp->options_in);
1094 dhcp->options_in = NULL;
1098 ptr = (u8_t *)dhcp->msg_in;
1099 /* proceed through struct dhcp_msg */
1100 for (i = 0; i < sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN; i++)
1102 *ptr++ = ((u8_t *)p->payload)[j++];
1103 /* reached end of pbuf? */
1106 /* proceed to next pbuf in chain */
1111 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_unfold_reply(): copied %u bytes into dhcp->msg_in[]\n", i));
1112 if (dhcp->options_in != NULL) {
1113 ptr = (u8_t *)dhcp->options_in;
1114 /* proceed through options */
1115 for (i = 0; i < dhcp->options_in_len; i++) {
1116 *ptr++ = ((u8_t *)p->payload)[j++];
1117 /* reached end of pbuf? */
1119 /* proceed to next pbuf in chain */
1124 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("dhcp_unfold_reply(): copied %u bytes to dhcp->options_in[]\n", i));
1130 * Free the incoming DHCP message including contiguous copy of
1134 static void dhcp_free_reply(struct dhcp *dhcp)
1136 if (dhcp->msg_in != NULL) {
1137 mem_free((void *)dhcp->msg_in);
1138 dhcp->msg_in = NULL;
1140 if (dhcp->options_in) {
1141 mem_free((void *)dhcp->options_in);
1142 dhcp->options_in = NULL;
1143 dhcp->options_in_len = 0;
1145 LWIP_DEBUGF(DHCP_DEBUG, ("dhcp_free_reply(): free'd\n"));
1150 * If an incoming DHCP message is in response to us, then trigger the state machine
1152 static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port)
1154 struct netif *netif = (struct netif *)arg;
1155 struct dhcp *dhcp = netif->dhcp;
1156 struct dhcp_msg *reply_msg = (struct dhcp_msg *)p->payload;
1160 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 3, ("dhcp_recv(pbuf = %p) from DHCP server %u.%u.%u.%u port %u\n", p,
1161 (unsigned int)(ntohl(addr->addr) >> 24 & 0xff), (unsigned int)(ntohl(addr->addr) >> 16 & 0xff),
1162 (unsigned int)(ntohl(addr->addr) >> 8 & 0xff), (unsigned int)(ntohl(addr->addr) & 0xff), port));
1163 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("pbuf->len = %u\n", p->len));
1164 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("pbuf->tot_len = %u\n", p->tot_len));
1165 /* prevent warnings about unused arguments */
1166 (void)pcb; (void)addr; (void)port;
1168 /* TODO: check packet length before reading them */
1169 if (reply_msg->op != DHCP_BOOTREPLY) {
1170 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 1, ("not a DHCP reply message, but type %u\n", reply_msg->op));
1175 /* iterate through hardware address and match against DHCP message */
1176 for (i = 0; i < netif->hwaddr_len; i++) {
1177 if (netif->hwaddr[i] != reply_msg->chaddr[i]) {
1178 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("netif->hwaddr[%u]==%02x != reply_msg->chaddr[%u]==%02x\n",
1179 i, netif->hwaddr[i], i, reply_msg->chaddr[i]));
1185 /* match transaction ID against what we expected */
1186 if (ntohl(reply_msg->xid) != dhcp->xid) {
1187 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("transaction id mismatch\n"));
1192 /* option fields could be unfold? */
1193 if (dhcp_unfold_reply(dhcp) != ERR_OK) {
1194 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("problem unfolding DHCP message - too short on memory?\n"));
1200 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("searching DHCP_OPTION_MESSAGE_TYPE\n"));
1201 /* obtain pointer to DHCP message type */
1202 options_ptr = dhcp_get_option_ptr(dhcp, DHCP_OPTION_MESSAGE_TYPE);
1203 if (options_ptr == NULL) {
1204 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 1, ("DHCP_OPTION_MESSAGE_TYPE option not found\n"));
1210 /* read DHCP message type */
1211 msg_type = dhcp_get_option_byte(options_ptr + 2);
1212 /* message type is DHCP ACK? */
1213 if (msg_type == DHCP_ACK) {
1214 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 1, ("DHCP_ACK received\n"));
1215 /* in requesting state? */
1216 if (dhcp->state == DHCP_REQUESTING) {
1217 dhcp_handle_ack(netif);
1218 dhcp->request_timeout = 0;
1219 #if DHCP_DOES_ARP_CHECK
1220 /* check if the acknowledged lease address is already in use */
1223 /* bind interface to the acknowledged lease address */
1227 /* already bound to the given lease address? */
1228 else if ((dhcp->state == DHCP_REBOOTING) || (dhcp->state == DHCP_REBINDING) || (dhcp->state == DHCP_RENEWING)) {
1229 dhcp->request_timeout = 0;
1233 /* received a DHCP_NAK in appropriate state? */
1234 else if ((msg_type == DHCP_NAK) &&
1235 ((dhcp->state == DHCP_REBOOTING) || (dhcp->state == DHCP_REQUESTING) ||
1236 (dhcp->state == DHCP_REBINDING) || (dhcp->state == DHCP_RENEWING ))) {
1237 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 1, ("DHCP_NAK received\n"));
1238 dhcp->request_timeout = 0;
1239 dhcp_handle_nak(netif);
1241 /* received a DHCP_OFFER in DHCP_SELECTING state? */
1242 else if ((msg_type == DHCP_OFFER) && (dhcp->state == DHCP_SELECTING)) {
1243 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 1, ("DHCP_OFFER received in DHCP_SELECTING state\n"));
1244 dhcp->request_timeout = 0;
1245 /* remember offered lease */
1246 dhcp_handle_offer(netif);
1253 static err_t dhcp_create_request(struct netif *netif)
1255 struct dhcp *dhcp = netif->dhcp;
1257 LWIP_ASSERT("dhcp_create_request: dhcp->p_out == NULL", dhcp->p_out == NULL);
1258 LWIP_ASSERT("dhcp_create_request: dhcp->msg_out == NULL", dhcp->msg_out == NULL);
1259 dhcp->p_out = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcp_msg), PBUF_RAM);
1260 if (dhcp->p_out == NULL) {
1261 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("dhcp_create_request(): could not allocate pbuf\n"));
1264 /* give unique transaction identifier to this request */
1267 dhcp->msg_out = (struct dhcp_msg *)dhcp->p_out->payload;
1269 dhcp->msg_out->op = DHCP_BOOTREQUEST;
1270 /* TODO: make link layer independent */
1271 dhcp->msg_out->htype = DHCP_HTYPE_ETH;
1272 /* TODO: make link layer independent */
1273 dhcp->msg_out->hlen = DHCP_HLEN_ETH;
1274 dhcp->msg_out->hops = 0;
1275 dhcp->msg_out->xid = htonl(dhcp->xid);
1276 dhcp->msg_out->secs = 0;
1277 dhcp->msg_out->flags = 0;
1278 dhcp->msg_out->ciaddr.addr = netif->ip_addr.addr;
1279 dhcp->msg_out->yiaddr.addr = 0;
1280 dhcp->msg_out->siaddr.addr = 0;
1281 dhcp->msg_out->giaddr.addr = 0;
1282 for (i = 0; i < DHCP_CHADDR_LEN; i++) {
1283 /* copy netif hardware address, pad with zeroes */
1284 dhcp->msg_out->chaddr[i] = (i < netif->hwaddr_len) ? netif->hwaddr[i] : 0/* pad byte*/;
1286 for (i = 0; i < DHCP_SNAME_LEN; i++) dhcp->msg_out->sname[i] = 0;
1287 for (i = 0; i < DHCP_FILE_LEN; i++) dhcp->msg_out->file[i] = 0;
1288 dhcp->msg_out->cookie = htonl(0x63825363UL);
1289 dhcp->options_out_len = 0;
1290 /* fill options field with an incrementing array (for debugging purposes) */
1291 for (i = 0; i < DHCP_OPTIONS_LEN; i++) dhcp->msg_out->options[i] = i;
1295 static void dhcp_delete_request(struct netif *netif)
1297 struct dhcp *dhcp = netif->dhcp;
1298 LWIP_ASSERT("dhcp_free_msg: dhcp->p_out != NULL", dhcp->p_out != NULL);
1299 LWIP_ASSERT("dhcp_free_msg: dhcp->msg_out != NULL", dhcp->msg_out != NULL);
1300 pbuf_free(dhcp->p_out);
1302 dhcp->msg_out = NULL;
1306 * Add a DHCP message trailer
1308 * Adds the END option to the DHCP message, and if
1309 * necessary, up to three padding bytes.
1312 static void dhcp_option_trailer(struct dhcp *dhcp)
1314 LWIP_ASSERT("dhcp_option_trailer: dhcp->msg_out != NULL\n", dhcp->msg_out != NULL);
1315 LWIP_ASSERT("dhcp_option_trailer: dhcp->options_out_len < DHCP_OPTIONS_LEN\n", dhcp->options_out_len < DHCP_OPTIONS_LEN);
1316 dhcp->msg_out->options[dhcp->options_out_len++] = DHCP_OPTION_END;
1317 /* packet is too small, or not 4 byte aligned? */
1318 while ((dhcp->options_out_len < DHCP_MIN_OPTIONS_LEN) || (dhcp->options_out_len & 3)) {
1319 /* LWIP_DEBUGF(DHCP_DEBUG, ("dhcp_option_trailer: dhcp->options_out_len=%u, DHCP_OPTIONS_LEN=%u", dhcp->options_out_len, DHCP_OPTIONS_LEN)); */
1320 LWIP_ASSERT("dhcp_option_trailer: dhcp->options_out_len < DHCP_OPTIONS_LEN\n", dhcp->options_out_len < DHCP_OPTIONS_LEN);
1321 /* add a fill/padding byte */
1322 dhcp->msg_out->options[dhcp->options_out_len++] = 0;
1327 * Find the offset of a DHCP option inside the DHCP message.
1329 * @param client DHCP client
1330 * @param option_type
1332 * @return a byte offset into the UDP message where the option was found, or
1333 * zero if the given option was not found.
1335 static u8_t *dhcp_get_option_ptr(struct dhcp *dhcp, u8_t option_type)
1337 u8_t overload = DHCP_OVERLOAD_NONE;
1339 /* options available? */
1340 if ((dhcp->options_in != NULL) && (dhcp->options_in_len > 0)) {
1341 /* start with options field */
1342 u8_t *options = (u8_t *)dhcp->options_in;
1344 /* at least 1 byte to read and no end marker, then at least 3 bytes to read? */
1345 while ((offset < dhcp->options_in_len) && (options[offset] != DHCP_OPTION_END)) {
1346 /* LWIP_DEBUGF(DHCP_DEBUG, ("msg_offset=%u, q->len=%u", msg_offset, q->len)); */
1347 /* are the sname and/or file field overloaded with options? */
1348 if (options[offset] == DHCP_OPTION_OVERLOAD) {
1349 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 2, ("overloaded message detected\n"));
1350 /* skip option type and length */
1352 overload = options[offset++];
1354 /* requested option found */
1355 else if (options[offset] == option_type) {
1356 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("option found at offset %u in options\n", offset));
1357 return &options[offset];
1360 LWIP_DEBUGF(DHCP_DEBUG, ("skipping option %u in options\n", options[offset]));
1361 /* skip option type */
1363 /* skip option length, and then length bytes */
1364 offset += 1 + options[offset];
1367 /* is this an overloaded message? */
1368 if (overload != DHCP_OVERLOAD_NONE) {
1370 if (overload == DHCP_OVERLOAD_FILE) {
1371 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 1, ("overloaded file field\n"));
1372 options = (u8_t *)&dhcp->msg_in->file;
1373 field_len = DHCP_FILE_LEN;
1374 } else if (overload == DHCP_OVERLOAD_SNAME) {
1375 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 1, ("overloaded sname field\n"));
1376 options = (u8_t *)&dhcp->msg_in->sname;
1377 field_len = DHCP_SNAME_LEN;
1378 /* TODO: check if else if () is necessary */
1380 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE | 1, ("overloaded sname and file field\n"));
1381 options = (u8_t *)&dhcp->msg_in->sname;
1382 field_len = DHCP_FILE_LEN + DHCP_SNAME_LEN;
1386 /* at least 1 byte to read and no end marker */
1387 while ((offset < field_len) && (options[offset] != DHCP_OPTION_END)) {
1388 if (options[offset] == option_type) {
1389 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("option found at offset=%u\n", offset));
1390 return &options[offset];
1393 LWIP_DEBUGF(DHCP_DEBUG | DBG_TRACE, ("skipping option %u\n", options[offset]));
1394 /* skip option type */
1396 offset += 1 + options[offset];
1405 * Return the byte of DHCP option data.
1407 * @param client DHCP client.
1408 * @param ptr pointer obtained by dhcp_get_option_ptr().
1410 * @return byte value at the given address.
1412 static u8_t dhcp_get_option_byte(u8_t *ptr)
1414 LWIP_DEBUGF(DHCP_DEBUG, ("option byte value=%u\n", *ptr));
1419 * Return the 16-bit value of DHCP option data.
1421 * @param client DHCP client.
1422 * @param ptr pointer obtained by dhcp_get_option_ptr().
1424 * @return byte value at the given address.
1426 static u16_t dhcp_get_option_short(u8_t *ptr)
1429 value = *ptr++ << 8;
1431 LWIP_DEBUGF(DHCP_DEBUG, ("option short value=%u\n", value));
1436 * Return the 32-bit value of DHCP option data.
1438 * @param client DHCP client.
1439 * @param ptr pointer obtained by dhcp_get_option_ptr().
1441 * @return byte value at the given address.
1443 static u32_t dhcp_get_option_long(u8_t *ptr)
1446 value = (u32_t)(*ptr++) << 24;
1447 value |= (u32_t)(*ptr++) << 16;
1448 value |= (u32_t)(*ptr++) << 8;
1449 value |= (u32_t)(*ptr++);
1450 LWIP_DEBUGF(DHCP_DEBUG, ("option long value=%lu\n", value));
1454 #endif /* LWIP_DHCP */