Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers lwip_dhcp.c Source File

lwip_dhcp.c

Go to the documentation of this file.
00001 /**
00002  * @file
00003  * Dynamic Host Configuration Protocol client
00004  *
00005  * @defgroup dhcp4 DHCPv4
00006  * @ingroup ip4
00007  * DHCP (IPv4) related functions
00008  * This is a DHCP client for the lwIP TCP/IP stack. It aims to conform
00009  * with RFC 2131 and RFC 2132.
00010  *
00011  * @todo:
00012  * - Support for interfaces other than Ethernet (SLIP, PPP, ...)
00013  *
00014  * Options:
00015  * @ref DHCP_COARSE_TIMER_SECS (recommended 60 which is a minute)
00016  * @ref DHCP_FINE_TIMER_MSECS (recommended 500 which equals TCP coarse timer)
00017  *
00018  * dhcp_start() starts a DHCP client instance which
00019  * configures the interface by obtaining an IP address lease and maintaining it.
00020  *
00021  * Use dhcp_release() to end the lease and use dhcp_stop()
00022  * to remove the DHCP client.
00023  *
00024  * @see LWIP_HOOK_DHCP_APPEND_OPTIONS
00025  * @see LWIP_HOOK_DHCP_PARSE_OPTION
00026  *
00027  * @see netifapi_dhcp4
00028  */
00029 
00030 /*
00031  * Copyright (c) 2001-2004 Leon Woestenberg <leon.woestenberg@gmx.net>
00032  * Copyright (c) 2001-2004 Axon Digital Design B.V., The Netherlands.
00033  * All rights reserved.
00034  *
00035  * Redistribution and use in source and binary forms, with or without modification,
00036  * are permitted provided that the following conditions are met:
00037  *
00038  * 1. Redistributions of source code must retain the above copyright notice,
00039  *    this list of conditions and the following disclaimer.
00040  * 2. Redistributions in binary form must reproduce the above copyright notice,
00041  *    this list of conditions and the following disclaimer in the documentation
00042  *    and/or other materials provided with the distribution.
00043  * 3. The name of the author may not be used to endorse or promote products
00044  *    derived from this software without specific prior written permission.
00045  *
00046  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
00047  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00048  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
00049  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00050  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
00051  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00052  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00053  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
00054  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
00055  * OF SUCH DAMAGE.
00056  *
00057  * This file is part of the lwIP TCP/IP stack.
00058  * The Swedish Institute of Computer Science and Adam Dunkels
00059  * are specifically granted permission to redistribute this
00060  * source code.
00061  *
00062  * Author: Leon Woestenberg <leon.woestenberg@gmx.net>
00063  *
00064  */
00065 
00066 #include "lwip/opt.h"
00067 
00068 #if LWIP_IPV4 && LWIP_DHCP /* don't build if not configured for use in lwipopts.h */
00069 
00070 #include "lwip/stats.h"
00071 #include "lwip/mem.h"
00072 #include "lwip/udp.h"
00073 #include "lwip/ip_addr.h"
00074 #include "lwip/netif.h"
00075 #include "lwip/def.h"
00076 #include "lwip/dhcp.h"
00077 #include "lwip/autoip.h"
00078 #include "lwip/dns.h"
00079 #include "lwip/etharp.h"
00080 #include "lwip/prot/dhcp.h"
00081 #include "lwip/prot/iana.h"
00082 
00083 #include <string.h>
00084 
00085 #ifdef LWIP_HOOK_FILENAME
00086 #include LWIP_HOOK_FILENAME
00087 #endif
00088 #ifndef LWIP_HOOK_DHCP_APPEND_OPTIONS
00089 #define LWIP_HOOK_DHCP_APPEND_OPTIONS(netif, dhcp, state, msg, msg_type, options_len_ptr)
00090 #endif
00091 #ifndef LWIP_HOOK_DHCP_PARSE_OPTION
00092 #define LWIP_HOOK_DHCP_PARSE_OPTION(netif, dhcp, state, msg, msg_type, option, len, pbuf, offset) do { LWIP_UNUSED_ARG(msg); } while(0)
00093 #endif
00094 
00095 /** DHCP_CREATE_RAND_XID: if this is set to 1, the xid is created using
00096  * LWIP_RAND() (this overrides DHCP_GLOBAL_XID)
00097  */
00098 #ifndef DHCP_CREATE_RAND_XID
00099 #define DHCP_CREATE_RAND_XID        1
00100 #endif
00101 
00102 /** Default for DHCP_GLOBAL_XID is 0xABCD0000
00103  * This can be changed by defining DHCP_GLOBAL_XID and DHCP_GLOBAL_XID_HEADER, e.g.
00104  *  \#define DHCP_GLOBAL_XID_HEADER "stdlib.h"
00105  *  \#define DHCP_GLOBAL_XID rand()
00106  */
00107 #ifdef DHCP_GLOBAL_XID_HEADER
00108 #include DHCP_GLOBAL_XID_HEADER /* include optional starting XID generation prototypes */
00109 #endif
00110 
00111 /** DHCP_OPTION_MAX_MSG_SIZE is set to the MTU
00112  * MTU is checked to be big enough in dhcp_start */
00113 #define DHCP_MAX_MSG_LEN(netif)        (netif->mtu)
00114 #define DHCP_MAX_MSG_LEN_MIN_REQUIRED  576
00115 /** Minimum length for reply before packet is parsed */
00116 #define DHCP_MIN_REPLY_LEN             44
00117 
00118 #define REBOOT_TRIES                2
00119 
00120 #if LWIP_DNS && LWIP_DHCP_MAX_DNS_SERVERS
00121 #if DNS_MAX_SERVERS > LWIP_DHCP_MAX_DNS_SERVERS
00122 #define LWIP_DHCP_PROVIDE_DNS_SERVERS LWIP_DHCP_MAX_DNS_SERVERS
00123 #else
00124 #define LWIP_DHCP_PROVIDE_DNS_SERVERS DNS_MAX_SERVERS
00125 #endif
00126 #else
00127 #define LWIP_DHCP_PROVIDE_DNS_SERVERS 0
00128 #endif
00129 
00130 /** Option handling: options are parsed in dhcp_parse_reply
00131  * and saved in an array where other functions can load them from.
00132  * This might be moved into the struct dhcp (not necessarily since
00133  * lwIP is single-threaded and the array is only used while in recv
00134  * callback). */
00135 enum dhcp_option_idx {
00136   DHCP_OPTION_IDX_OVERLOAD = 0,
00137   DHCP_OPTION_IDX_MSG_TYPE,
00138   DHCP_OPTION_IDX_SERVER_ID,
00139   DHCP_OPTION_IDX_LEASE_TIME,
00140   DHCP_OPTION_IDX_T1,
00141   DHCP_OPTION_IDX_T2,
00142   DHCP_OPTION_IDX_SUBNET_MASK,
00143   DHCP_OPTION_IDX_ROUTER,
00144 #if LWIP_DHCP_PROVIDE_DNS_SERVERS
00145   DHCP_OPTION_IDX_DNS_SERVER,
00146   DHCP_OPTION_IDX_DNS_SERVER_LAST = DHCP_OPTION_IDX_DNS_SERVER + LWIP_DHCP_PROVIDE_DNS_SERVERS - 1,
00147 #endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS */
00148 #if LWIP_DHCP_GET_NTP_SRV
00149   DHCP_OPTION_IDX_NTP_SERVER,
00150   DHCP_OPTION_IDX_NTP_SERVER_LAST = DHCP_OPTION_IDX_NTP_SERVER + LWIP_DHCP_MAX_NTP_SERVERS - 1,
00151 #endif /* LWIP_DHCP_GET_NTP_SRV */
00152   DHCP_OPTION_IDX_MAX
00153 };
00154 
00155 /** Holds the decoded option values, only valid while in dhcp_recv.
00156     @todo: move this into struct dhcp? */
00157 u32_t dhcp_rx_options_val[DHCP_OPTION_IDX_MAX];
00158 /** Holds a flag which option was received and is contained in dhcp_rx_options_val,
00159     only valid while in dhcp_recv.
00160     @todo: move this into struct dhcp? */
00161 u8_t  dhcp_rx_options_given[DHCP_OPTION_IDX_MAX];
00162 
00163 static u8_t dhcp_discover_request_options[] = {
00164   DHCP_OPTION_SUBNET_MASK,
00165   DHCP_OPTION_ROUTER,
00166   DHCP_OPTION_BROADCAST
00167 #if LWIP_DHCP_PROVIDE_DNS_SERVERS
00168   , DHCP_OPTION_DNS_SERVER
00169 #endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS */
00170 #if LWIP_DHCP_GET_NTP_SRV
00171   , DHCP_OPTION_NTP
00172 #endif /* LWIP_DHCP_GET_NTP_SRV */
00173 };
00174 
00175 #ifdef DHCP_GLOBAL_XID
00176 static u32_t xid;
00177 static u8_t xid_initialised;
00178 #endif /* DHCP_GLOBAL_XID */
00179 
00180 #define dhcp_option_given(dhcp, idx)          (dhcp_rx_options_given[idx] != 0)
00181 #define dhcp_got_option(dhcp, idx)            (dhcp_rx_options_given[idx] = 1)
00182 #define dhcp_clear_option(dhcp, idx)          (dhcp_rx_options_given[idx] = 0)
00183 #define dhcp_clear_all_options(dhcp)          (memset(dhcp_rx_options_given, 0, sizeof(dhcp_rx_options_given)))
00184 #define dhcp_get_option_value(dhcp, idx)      (dhcp_rx_options_val[idx])
00185 #define dhcp_set_option_value(dhcp, idx, val) (dhcp_rx_options_val[idx] = (val))
00186 
00187 static struct udp_pcb *dhcp_pcb;
00188 static u8_t dhcp_pcb_refcount;
00189 
00190 /* DHCP client state machine functions */
00191 static err_t dhcp_discover(struct netif *netif);
00192 static err_t dhcp_select(struct netif *netif);
00193 static void dhcp_bind(struct netif *netif);
00194 #if DHCP_DOES_ARP_CHECK
00195 static err_t dhcp_decline(struct netif *netif);
00196 #endif /* DHCP_DOES_ARP_CHECK */
00197 static err_t dhcp_rebind(struct netif *netif);
00198 static err_t dhcp_reboot(struct netif *netif);
00199 static void dhcp_set_state(struct dhcp *dhcp, u8_t new_state);
00200 
00201 /* receive, unfold, parse and free incoming messages */
00202 static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port);
00203 
00204 /* set the DHCP timers */
00205 static void dhcp_timeout(struct netif *netif);
00206 static void dhcp_t1_timeout(struct netif *netif);
00207 static void dhcp_t2_timeout(struct netif *netif);
00208 
00209 /* build outgoing messages */
00210 /* create a DHCP message, fill in common headers */
00211 static struct pbuf *dhcp_create_msg(struct netif *netif, struct dhcp *dhcp, u8_t message_type, u16_t *options_out_len);
00212 /* add a DHCP option (type, then length in bytes) */
00213 static u16_t dhcp_option(u16_t options_out_len, u8_t *options, u8_t option_type, u8_t option_len);
00214 /* add option values */
00215 static u16_t dhcp_option_byte(u16_t options_out_len, u8_t *options, u8_t value);
00216 static u16_t dhcp_option_short(u16_t options_out_len, u8_t *options, u16_t value);
00217 static u16_t dhcp_option_long(u16_t options_out_len, u8_t *options, u32_t value);
00218 #if LWIP_NETIF_HOSTNAME
00219 static u16_t dhcp_option_hostname(u16_t options_out_len, u8_t *options, struct netif *netif);
00220 #endif /* LWIP_NETIF_HOSTNAME */
00221 /* always add the DHCP options trailer to end and pad */
00222 static void dhcp_option_trailer(u16_t options_out_len, u8_t *options, struct pbuf *p_out);
00223 
00224 /** Ensure DHCP PCB is allocated and bound */
00225 static err_t
00226 dhcp_inc_pcb_refcount(void)
00227 {
00228   if (dhcp_pcb_refcount == 0) {
00229     LWIP_ASSERT("dhcp_inc_pcb_refcount(): memory leak", dhcp_pcb == NULL);
00230 
00231     /* allocate UDP PCB */
00232     dhcp_pcb = udp_new();
00233 
00234     if (dhcp_pcb == NULL) {
00235       return ERR_MEM;
00236     }
00237 
00238     ip_set_option(dhcp_pcb, SOF_BROADCAST);
00239 
00240     /* set up local and remote port for the pcb -> listen on all interfaces on all src/dest IPs */
00241     udp_bind(dhcp_pcb, IP4_ADDR_ANY, LWIP_IANA_PORT_DHCP_CLIENT);
00242     udp_connect(dhcp_pcb, IP4_ADDR_ANY, LWIP_IANA_PORT_DHCP_SERVER);
00243     udp_recv(dhcp_pcb, dhcp_recv, NULL);
00244   }
00245 
00246   dhcp_pcb_refcount++;
00247 
00248   return ERR_OK;
00249 }
00250 
00251 /** Free DHCP PCB if the last netif stops using it */
00252 static void
00253 dhcp_dec_pcb_refcount(void)
00254 {
00255   LWIP_ASSERT("dhcp_pcb_refcount(): refcount error", (dhcp_pcb_refcount > 0));
00256   dhcp_pcb_refcount--;
00257 
00258   if (dhcp_pcb_refcount == 0) {
00259     udp_remove(dhcp_pcb);
00260     dhcp_pcb = NULL;
00261   }
00262 }
00263 
00264 /**
00265  * Back-off the DHCP client (because of a received NAK response).
00266  *
00267  * Back-off the DHCP client because of a received NAK. Receiving a
00268  * NAK means the client asked for something non-sensible, for
00269  * example when it tries to renew a lease obtained on another network.
00270  *
00271  * We clear any existing set IP address and restart DHCP negotiation
00272  * afresh (as per RFC2131 3.2.3).
00273  *
00274  * @param netif the netif under DHCP control
00275  */
00276 static void
00277 dhcp_handle_nak(struct netif *netif)
00278 {
00279   struct dhcp *dhcp = netif_dhcp_data(netif);
00280 
00281   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_handle_nak(netif=%p) %c%c%"U16_F"\n",
00282               (void *)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
00283   /* Change to a defined state - set this before assigning the address
00284      to ensure the callback can use dhcp_supplied_address() */
00285   dhcp_set_state(dhcp, DHCP_STATE_BACKING_OFF);
00286   /* remove IP address from interface (must no longer be used, as per RFC2131) */
00287   netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4);
00288   /* We can immediately restart discovery */
00289   dhcp_discover(netif);
00290 }
00291 
00292 #if DHCP_DOES_ARP_CHECK
00293 /**
00294  * Checks if the offered IP address is already in use.
00295  *
00296  * It does so by sending an ARP request for the offered address and
00297  * entering CHECKING state. If no ARP reply is received within a small
00298  * interval, the address is assumed to be free for use by us.
00299  *
00300  * @param netif the netif under DHCP control
00301  */
00302 static void
00303 dhcp_check(struct netif *netif)
00304 {
00305   struct dhcp *dhcp = netif_dhcp_data(netif);
00306   err_t result;
00307   u16_t msecs;
00308   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_check(netif=%p) %c%c\n", (void *)netif, (s16_t)netif->name[0],
00309               (s16_t)netif->name[1]));
00310   dhcp_set_state(dhcp, DHCP_STATE_CHECKING);
00311   /* create an ARP query for the offered IP address, expecting that no host
00312      responds, as the IP address should not be in use. */
00313   result = etharp_query(netif, &dhcp->offered_ip_addr, NULL);
00314   if (result != ERR_OK) {
00315     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("dhcp_check: could not perform ARP query\n"));
00316   }
00317   if (dhcp->tries < 255) {
00318     dhcp->tries++;
00319   }
00320   msecs = 500;
00321   dhcp->request_timeout = (u16_t)((msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS);
00322   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_check(): set request timeout %"U16_F" msecs\n", msecs));
00323 }
00324 #endif /* DHCP_DOES_ARP_CHECK */
00325 
00326 /**
00327  * Remember the configuration offered by a DHCP server.
00328  *
00329  * @param netif the netif under DHCP control
00330  */
00331 static void
00332 dhcp_handle_offer(struct netif *netif, struct dhcp_msg *msg_in)
00333 {
00334   struct dhcp *dhcp = netif_dhcp_data(netif);
00335 
00336   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_handle_offer(netif=%p) %c%c%"U16_F"\n",
00337               (void *)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
00338   /* obtain the server address */
00339   if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_SERVER_ID)) {
00340     dhcp->request_timeout = 0; /* stop timer */
00341 
00342     ip_addr_set_ip4_u32(&dhcp->server_ip_addr, lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_SERVER_ID)));
00343     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_handle_offer(): server 0x%08"X32_F"\n",
00344                 ip4_addr_get_u32(ip_2_ip4(&dhcp->server_ip_addr))));
00345     /* remember offered address */
00346     ip4_addr_copy(dhcp->offered_ip_addr, msg_in->yiaddr);
00347     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_handle_offer(): offer for 0x%08"X32_F"\n",
00348                 ip4_addr_get_u32(&dhcp->offered_ip_addr)));
00349 
00350     dhcp_select(netif);
00351   } else {
00352     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
00353                 ("dhcp_handle_offer(netif=%p) did not get server ID!\n", (void *)netif));
00354   }
00355 }
00356 
00357 /**
00358  * Select a DHCP server offer out of all offers.
00359  *
00360  * Simply select the first offer received.
00361  *
00362  * @param netif the netif under DHCP control
00363  * @return lwIP specific error (see error.h)
00364  */
00365 static err_t
00366 dhcp_select(struct netif *netif)
00367 {
00368   struct dhcp *dhcp;
00369   err_t result;
00370   u16_t msecs;
00371   u8_t i;
00372   struct pbuf *p_out;
00373   u16_t options_out_len;
00374 
00375   LWIP_ERROR("dhcp_select: netif != NULL", (netif != NULL), return ERR_ARG;);
00376   dhcp = netif_dhcp_data(netif);
00377   LWIP_ERROR("dhcp_select: dhcp != NULL", (dhcp != NULL), return ERR_VAL;);
00378 
00379   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_select(netif=%p) %c%c%"U16_F"\n", (void *)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
00380   dhcp_set_state(dhcp, DHCP_STATE_REQUESTING);
00381 
00382   /* create and initialize the DHCP message header */
00383   p_out = dhcp_create_msg(netif, dhcp, DHCP_REQUEST, &options_out_len);
00384   if (p_out != NULL) {
00385     struct dhcp_msg *msg_out = (struct dhcp_msg *)p_out->payload;
00386     options_out_len = dhcp_option(options_out_len, msg_out->options, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
00387     options_out_len = dhcp_option_short(options_out_len, msg_out->options, DHCP_MAX_MSG_LEN(netif));
00388 
00389     /* MUST request the offered IP address */
00390     options_out_len = dhcp_option(options_out_len, msg_out->options, DHCP_OPTION_REQUESTED_IP, 4);
00391     options_out_len = dhcp_option_long(options_out_len, msg_out->options, lwip_ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr)));
00392 
00393     options_out_len = dhcp_option(options_out_len, msg_out->options, DHCP_OPTION_SERVER_ID, 4);
00394     options_out_len = dhcp_option_long(options_out_len, msg_out->options, lwip_ntohl(ip4_addr_get_u32(ip_2_ip4(&dhcp->server_ip_addr))));
00395 
00396     options_out_len = dhcp_option(options_out_len, msg_out->options, DHCP_OPTION_PARAMETER_REQUEST_LIST, LWIP_ARRAYSIZE(dhcp_discover_request_options));
00397     for (i = 0; i < LWIP_ARRAYSIZE(dhcp_discover_request_options); i++) {
00398       options_out_len = dhcp_option_byte(options_out_len, msg_out->options, dhcp_discover_request_options[i]);
00399     }
00400 
00401 #if LWIP_NETIF_HOSTNAME
00402     options_out_len = dhcp_option_hostname(options_out_len, msg_out->options, netif);
00403 #endif /* LWIP_NETIF_HOSTNAME */
00404 
00405     LWIP_HOOK_DHCP_APPEND_OPTIONS(netif, dhcp, DHCP_STATE_REQUESTING, msg_out, DHCP_REQUEST, &options_out_len);
00406     dhcp_option_trailer(options_out_len, msg_out->options, p_out);
00407 
00408     /* send broadcast to any DHCP server */
00409     result = udp_sendto_if_src(dhcp_pcb, p_out, IP_ADDR_BROADCAST, LWIP_IANA_PORT_DHCP_SERVER, netif, IP4_ADDR_ANY);
00410     pbuf_free(p_out);
00411     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_select: REQUESTING\n"));
00412   } else {
00413     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("dhcp_select: could not allocate DHCP request\n"));
00414     result = ERR_MEM;
00415   }
00416   if (dhcp->tries < 255) {
00417     dhcp->tries++;
00418   }
00419   msecs = (u16_t)((dhcp->tries < 6 ? 1 << dhcp->tries : 60) * 1000);
00420   dhcp->request_timeout = (u16_t)((msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS);
00421   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_select(): set request timeout %"U16_F" msecs\n", msecs));
00422   return result;
00423 }
00424 
00425 /**
00426  * The DHCP timer that checks for lease renewal/rebind timeouts.
00427  * Must be called once a minute (see @ref DHCP_COARSE_TIMER_SECS).
00428  */
00429 void
00430 dhcp_coarse_tmr(void)
00431 {
00432   struct netif *netif;
00433   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_coarse_tmr()\n"));
00434   /* iterate through all network interfaces */
00435   NETIF_FOREACH(netif) {
00436     /* only act on DHCP configured interfaces */
00437     struct dhcp *dhcp = netif_dhcp_data(netif);
00438     if ((dhcp != NULL) && (dhcp->state != DHCP_STATE_OFF)) {
00439       /* compare lease time to expire timeout */
00440       if (dhcp->t0_timeout && (++dhcp->lease_used == dhcp->t0_timeout)) {
00441         LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_coarse_tmr(): t0 timeout\n"));
00442         /* this clients' lease time has expired */
00443         dhcp_release_and_stop(netif);
00444         dhcp_start(netif);
00445         /* timer is active (non zero), and triggers (zeroes) now? */
00446       } else if (dhcp->t2_rebind_time && (dhcp->t2_rebind_time-- == 1)) {
00447         LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_coarse_tmr(): t2 timeout\n"));
00448         /* this clients' rebind timeout triggered */
00449         dhcp_t2_timeout(netif);
00450         /* timer is active (non zero), and triggers (zeroes) now */
00451       } else if (dhcp->t1_renew_time && (dhcp->t1_renew_time-- == 1)) {
00452         LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_coarse_tmr(): t1 timeout\n"));
00453         /* this clients' renewal timeout triggered */
00454         dhcp_t1_timeout(netif);
00455       }
00456     }
00457   }
00458 }
00459 
00460 /**
00461  * DHCP transaction timeout handling (this function must be called every 500ms,
00462  * see @ref DHCP_FINE_TIMER_MSECS).
00463  *
00464  * A DHCP server is expected to respond within a short period of time.
00465  * This timer checks whether an outstanding DHCP request is timed out.
00466  */
00467 void
00468 dhcp_fine_tmr(void)
00469 {
00470   struct netif *netif;
00471   /* loop through netif's */
00472   NETIF_FOREACH(netif) {
00473     struct dhcp *dhcp = netif_dhcp_data(netif);
00474     /* only act on DHCP configured interfaces */
00475     if (dhcp != NULL) {
00476       /* timer is active (non zero), and is about to trigger now */
00477       if (dhcp->request_timeout > 1) {
00478         dhcp->request_timeout--;
00479       } else if (dhcp->request_timeout == 1) {
00480         dhcp->request_timeout--;
00481         /* { dhcp->request_timeout == 0 } */
00482         LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_fine_tmr(): request timeout\n"));
00483         /* this client's request timeout triggered */
00484         dhcp_timeout(netif);
00485       }
00486     }
00487   }
00488 }
00489 
00490 /**
00491  * A DHCP negotiation transaction, or ARP request, has timed out.
00492  *
00493  * The timer that was started with the DHCP or ARP request has
00494  * timed out, indicating no response was received in time.
00495  *
00496  * @param netif the netif under DHCP control
00497  */
00498 static void
00499 dhcp_timeout(struct netif *netif)
00500 {
00501   struct dhcp *dhcp = netif_dhcp_data(netif);
00502 
00503   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_timeout()\n"));
00504   /* back-off period has passed, or server selection timed out */
00505   if ((dhcp->state == DHCP_STATE_BACKING_OFF) || (dhcp->state == DHCP_STATE_SELECTING)) {
00506     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_timeout(): restarting discovery\n"));
00507     dhcp_discover(netif);
00508     /* receiving the requested lease timed out */
00509   } else if (dhcp->state == DHCP_STATE_REQUESTING) {
00510     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): REQUESTING, DHCP request timed out\n"));
00511     if (dhcp->tries <= 5) {
00512       dhcp_select(netif);
00513     } else {
00514       LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): REQUESTING, releasing, restarting\n"));
00515       dhcp_release_and_stop(netif);
00516       dhcp_start(netif);
00517     }
00518 #if DHCP_DOES_ARP_CHECK
00519     /* received no ARP reply for the offered address (which is good) */
00520   } else if (dhcp->state == DHCP_STATE_CHECKING) {
00521     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): CHECKING, ARP request timed out\n"));
00522     if (dhcp->tries <= 1) {
00523       dhcp_check(netif);
00524       /* no ARP replies on the offered address,
00525          looks like the IP address is indeed free */
00526     } else {
00527       /* bind the interface to the offered address */
00528       dhcp_bind(netif);
00529     }
00530 #endif /* DHCP_DOES_ARP_CHECK */
00531   } else if (dhcp->state == DHCP_STATE_REBOOTING) {
00532     if (dhcp->tries < REBOOT_TRIES) {
00533       dhcp_reboot(netif);
00534     } else {
00535       dhcp_discover(netif);
00536     }
00537   }
00538 }
00539 
00540 /**
00541  * The renewal period has timed out.
00542  *
00543  * @param netif the netif under DHCP control
00544  */
00545 static void
00546 dhcp_t1_timeout(struct netif *netif)
00547 {
00548   struct dhcp *dhcp = netif_dhcp_data(netif);
00549 
00550   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_t1_timeout()\n"));
00551   if ((dhcp->state == DHCP_STATE_REQUESTING) || (dhcp->state == DHCP_STATE_BOUND) ||
00552       (dhcp->state == DHCP_STATE_RENEWING)) {
00553     /* just retry to renew - note that the rebind timer (t2) will
00554      * eventually time-out if renew tries fail. */
00555     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
00556                 ("dhcp_t1_timeout(): must renew\n"));
00557     /* This slightly different to RFC2131: DHCPREQUEST will be sent from state
00558        DHCP_STATE_RENEWING, not DHCP_STATE_BOUND */
00559     dhcp_renew(netif);
00560     /* Calculate next timeout */
00561     if (((dhcp->t2_timeout - dhcp->lease_used) / 2) >= ((60 + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS)) {
00562       dhcp->t1_renew_time = (u16_t)((dhcp->t2_timeout - dhcp->lease_used) / 2);
00563     }
00564   }
00565 }
00566 
00567 /**
00568  * The rebind period has timed out.
00569  *
00570  * @param netif the netif under DHCP control
00571  */
00572 static void
00573 dhcp_t2_timeout(struct netif *netif)
00574 {
00575   struct dhcp *dhcp = netif_dhcp_data(netif);
00576 
00577   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_t2_timeout()\n"));
00578   if ((dhcp->state == DHCP_STATE_REQUESTING) || (dhcp->state == DHCP_STATE_BOUND) ||
00579       (dhcp->state == DHCP_STATE_RENEWING) || (dhcp->state == DHCP_STATE_REBINDING)) {
00580     /* just retry to rebind */
00581     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
00582                 ("dhcp_t2_timeout(): must rebind\n"));
00583     /* This slightly different to RFC2131: DHCPREQUEST will be sent from state
00584        DHCP_STATE_REBINDING, not DHCP_STATE_BOUND */
00585     dhcp_rebind(netif);
00586     /* Calculate next timeout */
00587     if (((dhcp->t0_timeout - dhcp->lease_used) / 2) >= ((60 + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS)) {
00588       dhcp->t2_rebind_time = (u16_t)((dhcp->t0_timeout - dhcp->lease_used) / 2);
00589     }
00590   }
00591 }
00592 
00593 /**
00594  * Handle a DHCP ACK packet
00595  *
00596  * @param netif the netif under DHCP control
00597  */
00598 static void
00599 dhcp_handle_ack(struct netif *netif, struct dhcp_msg *msg_in)
00600 {
00601   struct dhcp *dhcp = netif_dhcp_data(netif);
00602 
00603 #if LWIP_DHCP_PROVIDE_DNS_SERVERS || LWIP_DHCP_GET_NTP_SRV
00604   u8_t n;
00605 #endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS || LWIP_DHCP_GET_NTP_SRV */
00606 #if LWIP_DHCP_GET_NTP_SRV
00607   ip4_addr_t ntp_server_addrs[LWIP_DHCP_MAX_NTP_SERVERS];
00608 #endif
00609 
00610   /* clear options we might not get from the ACK */
00611   ip4_addr_set_zero(&dhcp->offered_sn_mask);
00612   ip4_addr_set_zero(&dhcp->offered_gw_addr);
00613 #if LWIP_DHCP_BOOTP_FILE
00614   ip4_addr_set_zero(&dhcp->offered_si_addr);
00615 #endif /* LWIP_DHCP_BOOTP_FILE */
00616 
00617   /* lease time given? */
00618   if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_LEASE_TIME)) {
00619     /* remember offered lease time */
00620     dhcp->offered_t0_lease = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_LEASE_TIME);
00621   }
00622   /* renewal period given? */
00623   if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_T1)) {
00624     /* remember given renewal period */
00625     dhcp->offered_t1_renew = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_T1);
00626   } else {
00627     /* calculate safe periods for renewal */
00628     dhcp->offered_t1_renew = dhcp->offered_t0_lease / 2;
00629   }
00630 
00631   /* renewal period given? */
00632   if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_T2)) {
00633     /* remember given rebind period */
00634     dhcp->offered_t2_rebind = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_T2);
00635   } else {
00636     /* calculate safe periods for rebinding (offered_t0_lease * 0.875 -> 87.5%)*/
00637     dhcp->offered_t2_rebind = (dhcp->offered_t0_lease * 7U) / 8U;
00638   }
00639 
00640   /* (y)our internet address */
00641   ip4_addr_copy(dhcp->offered_ip_addr, msg_in->yiaddr);
00642 
00643 #if LWIP_DHCP_BOOTP_FILE
00644   /* copy boot server address,
00645      boot file name copied in dhcp_parse_reply if not overloaded */
00646   ip4_addr_copy(dhcp->offered_si_addr, msg_in->siaddr);
00647 #endif /* LWIP_DHCP_BOOTP_FILE */
00648 
00649   /* subnet mask given? */
00650   if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_SUBNET_MASK)) {
00651     /* remember given subnet mask */
00652     ip4_addr_set_u32(&dhcp->offered_sn_mask, lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_SUBNET_MASK)));
00653     dhcp->subnet_mask_given = 1;
00654   } else {
00655     dhcp->subnet_mask_given = 0;
00656   }
00657 
00658   /* gateway router */
00659   if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_ROUTER)) {
00660     ip4_addr_set_u32(&dhcp->offered_gw_addr, lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_ROUTER)));
00661   }
00662 
00663 #if LWIP_DHCP_GET_NTP_SRV
00664   /* NTP servers */
00665   for (n = 0; (n < LWIP_DHCP_MAX_NTP_SERVERS) && dhcp_option_given(dhcp, DHCP_OPTION_IDX_NTP_SERVER + n); n++) {
00666     ip4_addr_set_u32(&ntp_server_addrs[n], lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_NTP_SERVER + n)));
00667   }
00668   dhcp_set_ntp_servers(n, ntp_server_addrs);
00669 #endif /* LWIP_DHCP_GET_NTP_SRV */
00670 
00671 #if LWIP_DHCP_PROVIDE_DNS_SERVERS
00672   /* DNS servers */
00673   for (n = 0; (n < LWIP_DHCP_PROVIDE_DNS_SERVERS) && dhcp_option_given(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n); n++) {
00674     ip_addr_t dns_addr;
00675     ip_addr_set_ip4_u32_val(dns_addr, lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n)));
00676     dns_setserver(n, &dns_addr,netif);
00677   }
00678 #endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS */
00679 }
00680 
00681 /**
00682  * @ingroup dhcp4
00683  * Set a statically allocated struct dhcp to work with.
00684  * Using this prevents dhcp_start to allocate it using mem_malloc.
00685  *
00686  * @param netif the netif for which to set the struct dhcp
00687  * @param dhcp (uninitialised) dhcp struct allocated by the application
00688  */
00689 void
00690 dhcp_set_struct(struct netif *netif, struct dhcp *dhcp)
00691 {
00692   LWIP_ASSERT_CORE_LOCKED();
00693   LWIP_ASSERT("netif != NULL", netif != NULL);
00694   LWIP_ASSERT("dhcp != NULL", dhcp != NULL);
00695   LWIP_ASSERT("netif already has a struct dhcp set", netif_dhcp_data(netif) == NULL);
00696 
00697   /* clear data structure */
00698   memset(dhcp, 0, sizeof(struct dhcp));
00699   /* dhcp_set_state(&dhcp, DHCP_STATE_OFF); */
00700   netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP, dhcp);
00701 }
00702 
00703 /**
00704  * @ingroup dhcp4
00705  * Removes a struct dhcp from a netif.
00706  *
00707  * ATTENTION: Only use this when not using dhcp_set_struct() to allocate the
00708  *            struct dhcp since the memory is passed back to the heap.
00709  *
00710  * @param netif the netif from which to remove the struct dhcp
00711  */
00712 void dhcp_cleanup(struct netif *netif)
00713 {
00714   LWIP_ASSERT_CORE_LOCKED();
00715   LWIP_ASSERT("netif != NULL", netif != NULL);
00716 
00717   if (netif_dhcp_data(netif) != NULL) {
00718     mem_free(netif_dhcp_data(netif));
00719     netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP, NULL);
00720   }
00721 }
00722 
00723 /**
00724  * @ingroup dhcp4
00725  * Start DHCP negotiation for a network interface.
00726  *
00727  * If no DHCP client instance was attached to this interface,
00728  * a new client is created first. If a DHCP client instance
00729  * was already present, it restarts negotiation.
00730  *
00731  * @param netif The lwIP network interface
00732  * @return lwIP error code
00733  * - ERR_OK - No error
00734  * - ERR_MEM - Out of memory
00735  */
00736 err_t
00737 dhcp_start(struct netif *netif)
00738 {
00739   struct dhcp *dhcp;
00740   err_t result;
00741 
00742   LWIP_ASSERT_CORE_LOCKED();
00743   LWIP_ERROR("netif != NULL", (netif != NULL), return ERR_ARG;);
00744   LWIP_ERROR("netif is not up, old style port?", netif_is_up(netif), return ERR_ARG;);
00745   dhcp = netif_dhcp_data(netif);
00746   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_start(netif=%p) %c%c%"U16_F"\n", (void *)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
00747 
00748   /* check MTU of the netif */
00749   if (netif->mtu < DHCP_MAX_MSG_LEN_MIN_REQUIRED) {
00750     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): Cannot use this netif with DHCP: MTU is too small\n"));
00751     return ERR_MEM;
00752   }
00753 
00754   /* no DHCP client attached yet? */
00755   if (dhcp == NULL) {
00756     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): mallocing new DHCP client\n"));
00757     dhcp = (struct dhcp *)mem_malloc(sizeof(struct dhcp));
00758     if (dhcp == NULL) {
00759       LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): could not allocate dhcp\n"));
00760       return ERR_MEM;
00761     }
00762 
00763     /* store this dhcp client in the netif */
00764     netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP, dhcp);
00765     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): allocated dhcp"));
00766     /* already has DHCP client attached */
00767   } else {
00768     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_start(): restarting DHCP configuration\n"));
00769 
00770     if (dhcp->pcb_allocated != 0) {
00771       dhcp_dec_pcb_refcount(); /* free DHCP PCB if not needed any more */
00772     }
00773     /* dhcp is cleared below, no need to reset flag*/
00774   }
00775 
00776   /* clear data structure */
00777   memset(dhcp, 0, sizeof(struct dhcp));
00778   /* dhcp_set_state(&dhcp, DHCP_STATE_OFF); */
00779 
00780   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): starting DHCP configuration\n"));
00781 
00782   if (dhcp_inc_pcb_refcount() != ERR_OK) { /* ensure DHCP PCB is allocated */
00783     return ERR_MEM;
00784   }
00785   dhcp->pcb_allocated = 1;
00786 
00787   if (!netif_is_link_up(netif)) {
00788     /* set state INIT and wait for dhcp_network_changed() to call dhcp_discover() */
00789     dhcp_set_state(dhcp, DHCP_STATE_INIT);
00790     return ERR_OK;
00791   }
00792 
00793   /* (re)start the DHCP negotiation */
00794   result = dhcp_discover(netif);
00795   if (result != ERR_OK) {
00796     /* free resources allocated above */
00797     dhcp_release_and_stop(netif);
00798     return ERR_MEM;
00799   }
00800   return result;
00801 }
00802 
00803 /**
00804  * @ingroup dhcp4
00805  * Inform a DHCP server of our manual configuration.
00806  *
00807  * This informs DHCP servers of our fixed IP address configuration
00808  * by sending an INFORM message. It does not involve DHCP address
00809  * configuration, it is just here to be nice to the network.
00810  *
00811  * @param netif The lwIP network interface
00812  */
00813 void
00814 dhcp_inform(struct netif *netif)
00815 {
00816   struct dhcp dhcp;
00817   struct pbuf *p_out;
00818   u16_t options_out_len;
00819 
00820   LWIP_ASSERT_CORE_LOCKED();
00821   LWIP_ERROR("netif != NULL", (netif != NULL), return;);
00822 
00823   if (dhcp_inc_pcb_refcount() != ERR_OK) { /* ensure DHCP PCB is allocated */
00824     return;
00825   }
00826 
00827   memset(&dhcp, 0, sizeof(struct dhcp));
00828   dhcp_set_state(&dhcp, DHCP_STATE_INFORMING);
00829 
00830   /* create and initialize the DHCP message header */
00831   p_out = dhcp_create_msg(netif, &dhcp, DHCP_INFORM, &options_out_len);
00832   if (p_out != NULL) {
00833     struct dhcp_msg *msg_out = (struct dhcp_msg *)p_out->payload;
00834     options_out_len = dhcp_option(options_out_len, msg_out->options, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
00835     options_out_len = dhcp_option_short(options_out_len, msg_out->options, DHCP_MAX_MSG_LEN(netif));
00836 
00837     LWIP_HOOK_DHCP_APPEND_OPTIONS(netif, &dhcp, DHCP_STATE_INFORMING, msg_out, DHCP_INFORM, &options_out_len);
00838     dhcp_option_trailer(options_out_len, msg_out->options, p_out);
00839 
00840     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_inform: INFORMING\n"));
00841 
00842     udp_sendto_if(dhcp_pcb, p_out, IP_ADDR_BROADCAST, LWIP_IANA_PORT_DHCP_SERVER, netif);
00843 
00844     pbuf_free(p_out);
00845   } else {
00846     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_inform: could not allocate DHCP request\n"));
00847   }
00848 
00849   dhcp_dec_pcb_refcount(); /* delete DHCP PCB if not needed any more */
00850 }
00851 
00852 /** Handle a possible change in the network configuration.
00853  *
00854  * This enters the REBOOTING state to verify that the currently bound
00855  * address is still valid.
00856  */
00857 void
00858 dhcp_network_changed(struct netif *netif)
00859 {
00860   struct dhcp *dhcp = netif_dhcp_data(netif);
00861 
00862   if (!dhcp) {
00863     return;
00864   }
00865   switch (dhcp->state) {
00866     case DHCP_STATE_REBINDING:
00867     case DHCP_STATE_RENEWING:
00868     case DHCP_STATE_BOUND:
00869     case DHCP_STATE_REBOOTING:
00870       dhcp->tries = 0;
00871       dhcp_reboot(netif);
00872       break;
00873     case DHCP_STATE_OFF:
00874       /* stay off */
00875       break;
00876     default:
00877       LWIP_ASSERT("invalid dhcp->state", dhcp->state <= DHCP_STATE_BACKING_OFF);
00878       /* INIT/REQUESTING/CHECKING/BACKING_OFF restart with new 'rid' because the
00879          state changes, SELECTING: continue with current 'rid' as we stay in the
00880          same state */
00881 #if LWIP_DHCP_AUTOIP_COOP
00882       if (dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) {
00883         autoip_stop(netif);
00884         dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF;
00885       }
00886 #endif /* LWIP_DHCP_AUTOIP_COOP */
00887       /* ensure we start with short timeouts, even if already discovering */
00888       dhcp->tries = 0;
00889       dhcp_discover(netif);
00890       break;
00891   }
00892 }
00893 
00894 #if DHCP_DOES_ARP_CHECK
00895 /**
00896  * Match an ARP reply with the offered IP address:
00897  * check whether the offered IP address is not in use using ARP
00898  *
00899  * @param netif the network interface on which the reply was received
00900  * @param addr The IP address we received a reply from
00901  */
00902 void
00903 dhcp_arp_reply(struct netif *netif, const ip4_addr_t *addr)
00904 {
00905   struct dhcp *dhcp;
00906 
00907   LWIP_ERROR("netif != NULL", (netif != NULL), return;);
00908   dhcp = netif_dhcp_data(netif);
00909   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_arp_reply()\n"));
00910   /* is a DHCP client doing an ARP check? */
00911   if ((dhcp != NULL) && (dhcp->state == DHCP_STATE_CHECKING)) {
00912     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_arp_reply(): CHECKING, arp reply for 0x%08"X32_F"\n",
00913                 ip4_addr_get_u32(addr)));
00914     /* did a host respond with the address we
00915        were offered by the DHCP server? */
00916     if (ip4_addr_cmp(addr, &dhcp->offered_ip_addr)) {
00917       /* we will not accept the offered address */
00918       LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING,
00919                   ("dhcp_arp_reply(): arp reply matched with offered address, declining\n"));
00920       dhcp_decline(netif);
00921     }
00922   }
00923 }
00924 
00925 /**
00926  * Decline an offered lease.
00927  *
00928  * Tell the DHCP server we do not accept the offered address.
00929  * One reason to decline the lease is when we find out the address
00930  * is already in use by another host (through ARP).
00931  *
00932  * @param netif the netif under DHCP control
00933  */
00934 static err_t
00935 dhcp_decline(struct netif *netif)
00936 {
00937   struct dhcp *dhcp = netif_dhcp_data(netif);
00938   err_t result;
00939   u16_t msecs;
00940   struct pbuf *p_out;
00941   u16_t options_out_len;
00942 
00943   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_decline()\n"));
00944   dhcp_set_state(dhcp, DHCP_STATE_BACKING_OFF);
00945   /* create and initialize the DHCP message header */
00946   p_out = dhcp_create_msg(netif, dhcp, DHCP_DECLINE, &options_out_len);
00947   if (p_out != NULL) {
00948     struct dhcp_msg *msg_out = (struct dhcp_msg *)p_out->payload;
00949     options_out_len = dhcp_option(options_out_len, msg_out->options, DHCP_OPTION_REQUESTED_IP, 4);
00950     options_out_len = dhcp_option_long(options_out_len, msg_out->options, lwip_ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr)));
00951 
00952     LWIP_HOOK_DHCP_APPEND_OPTIONS(netif, dhcp, DHCP_STATE_BACKING_OFF, msg_out, DHCP_DECLINE, &options_out_len);
00953     dhcp_option_trailer(options_out_len, msg_out->options, p_out);
00954 
00955     /* per section 4.4.4, broadcast DECLINE messages */
00956     result = udp_sendto_if_src(dhcp_pcb, p_out, IP_ADDR_BROADCAST, LWIP_IANA_PORT_DHCP_SERVER, netif, IP4_ADDR_ANY);
00957     pbuf_free(p_out);
00958     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_decline: BACKING OFF\n"));
00959   } else {
00960     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
00961                 ("dhcp_decline: could not allocate DHCP request\n"));
00962     result = ERR_MEM;
00963   }
00964   if (dhcp->tries < 255) {
00965     dhcp->tries++;
00966   }
00967   msecs = 10 * 1000;
00968   dhcp->request_timeout = (u16_t)((msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS);
00969   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_decline(): set request timeout %"U16_F" msecs\n", msecs));
00970   return result;
00971 }
00972 #endif /* DHCP_DOES_ARP_CHECK */
00973 
00974 
00975 /**
00976  * Start the DHCP process, discover a DHCP server.
00977  *
00978  * @param netif the netif under DHCP control
00979  */
00980 static err_t
00981 dhcp_discover(struct netif *netif)
00982 {
00983   struct dhcp *dhcp = netif_dhcp_data(netif);
00984   err_t result = ERR_OK;
00985   u16_t msecs;
00986   u8_t i;
00987   struct pbuf *p_out;
00988   u16_t options_out_len;
00989 
00990   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover()\n"));
00991 
00992   ip4_addr_set_any(&dhcp->offered_ip_addr);
00993   dhcp_set_state(dhcp, DHCP_STATE_SELECTING);
00994   /* create and initialize the DHCP message header */
00995   p_out = dhcp_create_msg(netif, dhcp, DHCP_DISCOVER, &options_out_len);
00996   if (p_out != NULL) {
00997     struct dhcp_msg *msg_out = (struct dhcp_msg *)p_out->payload;
00998     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: making request\n"));
00999 
01000     options_out_len = dhcp_option(options_out_len, msg_out->options, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
01001     options_out_len = dhcp_option_short(options_out_len, msg_out->options, DHCP_MAX_MSG_LEN(netif));
01002 
01003     options_out_len = dhcp_option(options_out_len, msg_out->options, DHCP_OPTION_PARAMETER_REQUEST_LIST, LWIP_ARRAYSIZE(dhcp_discover_request_options));
01004     for (i = 0; i < LWIP_ARRAYSIZE(dhcp_discover_request_options); i++) {
01005       options_out_len = dhcp_option_byte(options_out_len, msg_out->options, dhcp_discover_request_options[i]);
01006     }
01007     LWIP_HOOK_DHCP_APPEND_OPTIONS(netif, dhcp, DHCP_STATE_SELECTING, msg_out, DHCP_DISCOVER, &options_out_len);
01008     dhcp_option_trailer(options_out_len, msg_out->options, p_out);
01009 
01010     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, LWIP_IANA_PORT_DHCP_SERVER)\n"));
01011     udp_sendto_if_src(dhcp_pcb, p_out, IP_ADDR_BROADCAST, LWIP_IANA_PORT_DHCP_SERVER, netif, IP4_ADDR_ANY);
01012     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: deleting()ing\n"));
01013     pbuf_free(p_out);
01014     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover: SELECTING\n"));
01015   } else {
01016     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_discover: could not allocate DHCP request\n"));
01017   }
01018   if (dhcp->tries < 255) {
01019     dhcp->tries++;
01020   }
01021 #if LWIP_DHCP_AUTOIP_COOP
01022   if (dhcp->tries >= LWIP_DHCP_AUTOIP_COOP_TRIES && dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_OFF) {
01023     dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_ON;
01024     autoip_start(netif);
01025   }
01026 #endif /* LWIP_DHCP_AUTOIP_COOP */
01027   msecs = (u16_t)((dhcp->tries < 6 ? 1 << dhcp->tries : 60) * 1000);
01028   dhcp->request_timeout = (u16_t)((msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS);
01029   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover(): set request timeout %"U16_F" msecs\n", msecs));
01030   return result;
01031 }
01032 
01033 
01034 /**
01035  * Bind the interface to the offered IP address.
01036  *
01037  * @param netif network interface to bind to the offered address
01038  */
01039 static void
01040 dhcp_bind(struct netif *netif)
01041 {
01042   u32_t timeout;
01043   struct dhcp *dhcp;
01044   ip4_addr_t sn_mask, gw_addr;
01045   LWIP_ERROR("dhcp_bind: netif != NULL", (netif != NULL), return;);
01046   dhcp = netif_dhcp_data(netif);
01047   LWIP_ERROR("dhcp_bind: dhcp != NULL", (dhcp != NULL), return;);
01048   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(netif=%p) %c%c%"U16_F"\n", (void *)netif, netif->name[0], netif->name[1], (u16_t)netif->num));
01049 
01050   /* reset time used of lease */
01051   dhcp->lease_used = 0;
01052 
01053   if (dhcp->offered_t0_lease != 0xffffffffUL) {
01054     /* set renewal period timer */
01055     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t0 renewal timer %"U32_F" secs\n", dhcp->offered_t0_lease));
01056     timeout = (dhcp->offered_t0_lease + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS;
01057     if (timeout > 0xffff) {
01058       timeout = 0xffff;
01059     }
01060     dhcp->t0_timeout = (u16_t)timeout;
01061     if (dhcp->t0_timeout == 0) {
01062       dhcp->t0_timeout = 1;
01063     }
01064     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t0_lease * 1000));
01065   }
01066 
01067   /* temporary DHCP lease? */
01068   if (dhcp->offered_t1_renew != 0xffffffffUL) {
01069     /* set renewal period timer */
01070     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t1 renewal timer %"U32_F" secs\n", dhcp->offered_t1_renew));
01071     timeout = (dhcp->offered_t1_renew + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS;
01072     if (timeout > 0xffff) {
01073       timeout = 0xffff;
01074     }
01075     dhcp->t1_timeout = (u16_t)timeout;
01076     if (dhcp->t1_timeout == 0) {
01077       dhcp->t1_timeout = 1;
01078     }
01079     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t1_renew * 1000));
01080     dhcp->t1_renew_time = dhcp->t1_timeout;
01081   }
01082   /* set renewal period timer */
01083   if (dhcp->offered_t2_rebind != 0xffffffffUL) {
01084     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t2 rebind timer %"U32_F" secs\n", dhcp->offered_t2_rebind));
01085     timeout = (dhcp->offered_t2_rebind + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS;
01086     if (timeout > 0xffff) {
01087       timeout = 0xffff;
01088     }
01089     dhcp->t2_timeout = (u16_t)timeout;
01090     if (dhcp->t2_timeout == 0) {
01091       dhcp->t2_timeout = 1;
01092     }
01093     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t2_rebind * 1000));
01094     dhcp->t2_rebind_time = dhcp->t2_timeout;
01095   }
01096 
01097   /* If we have sub 1 minute lease, t2 and t1 will kick in at the same time. */
01098   if ((dhcp->t1_timeout >= dhcp->t2_timeout) && (dhcp->t2_timeout > 0)) {
01099     dhcp->t1_timeout = 0;
01100   }
01101 
01102   if (dhcp->subnet_mask_given) {
01103     /* copy offered network mask */
01104     ip4_addr_copy(sn_mask, dhcp->offered_sn_mask);
01105   } else {
01106     /* subnet mask not given, choose a safe subnet mask given the network class */
01107     u8_t first_octet = ip4_addr1(&dhcp->offered_ip_addr);
01108     if (first_octet <= 127) {
01109       ip4_addr_set_u32(&sn_mask, PP_HTONL(0xff000000UL));
01110     } else if (first_octet >= 192) {
01111       ip4_addr_set_u32(&sn_mask, PP_HTONL(0xffffff00UL));
01112     } else {
01113       ip4_addr_set_u32(&sn_mask, PP_HTONL(0xffff0000UL));
01114     }
01115   }
01116 
01117   ip4_addr_copy(gw_addr, dhcp->offered_gw_addr);
01118   /* gateway address not given? */
01119   if (ip4_addr_isany_val(gw_addr)) {
01120     /* copy network address */
01121     ip4_addr_get_network(&gw_addr, &dhcp->offered_ip_addr, &sn_mask);
01122     /* use first host address on network as gateway */
01123     ip4_addr_set_u32(&gw_addr, ip4_addr_get_u32(&gw_addr) | PP_HTONL(0x00000001UL));
01124   }
01125 
01126 #if LWIP_DHCP_AUTOIP_COOP
01127   if (dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) {
01128     autoip_stop(netif);
01129     dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF;
01130   }
01131 #endif /* LWIP_DHCP_AUTOIP_COOP */
01132 
01133   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): IP: 0x%08"X32_F" SN: 0x%08"X32_F" GW: 0x%08"X32_F"\n",
01134               ip4_addr_get_u32(&dhcp->offered_ip_addr), ip4_addr_get_u32(&sn_mask), ip4_addr_get_u32(&gw_addr)));
01135   /* netif is now bound to DHCP leased address - set this before assigning the address
01136      to ensure the callback can use dhcp_supplied_address() */
01137   dhcp_set_state(dhcp, DHCP_STATE_BOUND);
01138 
01139   netif_set_addr(netif, &dhcp->offered_ip_addr, &sn_mask, &gw_addr);
01140   /* interface is used by routing now that an address is set */
01141 }
01142 
01143 /**
01144  * @ingroup dhcp4
01145  * Renew an existing DHCP lease at the involved DHCP server.
01146  *
01147  * @param netif network interface which must renew its lease
01148  */
01149 err_t
01150 dhcp_renew(struct netif *netif)
01151 {
01152   struct dhcp *dhcp = netif_dhcp_data(netif);
01153   err_t result;
01154   u16_t msecs;
01155   u8_t i;
01156   struct pbuf *p_out;
01157   u16_t options_out_len;
01158 
01159   LWIP_ASSERT_CORE_LOCKED();
01160   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_renew()\n"));
01161   dhcp_set_state(dhcp, DHCP_STATE_RENEWING);
01162 
01163   /* create and initialize the DHCP message header */
01164   p_out = dhcp_create_msg(netif, dhcp, DHCP_REQUEST, &options_out_len);
01165   if (p_out != NULL) {
01166     struct dhcp_msg *msg_out = (struct dhcp_msg *)p_out->payload;
01167     options_out_len = dhcp_option(options_out_len, msg_out->options, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
01168     options_out_len = dhcp_option_short(options_out_len, msg_out->options, DHCP_MAX_MSG_LEN(netif));
01169 
01170     options_out_len = dhcp_option(options_out_len, msg_out->options, DHCP_OPTION_PARAMETER_REQUEST_LIST, LWIP_ARRAYSIZE(dhcp_discover_request_options));
01171     for (i = 0; i < LWIP_ARRAYSIZE(dhcp_discover_request_options); i++) {
01172       options_out_len = dhcp_option_byte(options_out_len, msg_out->options, dhcp_discover_request_options[i]);
01173     }
01174 
01175 #if LWIP_NETIF_HOSTNAME
01176     options_out_len = dhcp_option_hostname(options_out_len, msg_out->options, netif);
01177 #endif /* LWIP_NETIF_HOSTNAME */
01178 
01179     LWIP_HOOK_DHCP_APPEND_OPTIONS(netif, dhcp, DHCP_STATE_RENEWING, msg_out, DHCP_REQUEST, &options_out_len);
01180     dhcp_option_trailer(options_out_len, msg_out->options, p_out);
01181 
01182     result = udp_sendto_if(dhcp_pcb, p_out, &dhcp->server_ip_addr, LWIP_IANA_PORT_DHCP_SERVER, netif);
01183     pbuf_free(p_out);
01184 
01185     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_renew: RENEWING\n"));
01186   } else {
01187     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_renew: could not allocate DHCP request\n"));
01188     result = ERR_MEM;
01189   }
01190   if (dhcp->tries < 255) {
01191     dhcp->tries++;
01192   }
01193   /* back-off on retries, but to a maximum of 20 seconds */
01194   msecs = (u16_t)(dhcp->tries < 10 ? dhcp->tries * 2000 : 20 * 1000);
01195   dhcp->request_timeout = (u16_t)((msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS);
01196   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_renew(): set request timeout %"U16_F" msecs\n", msecs));
01197   return result;
01198 }
01199 
01200 /**
01201  * Rebind with a DHCP server for an existing DHCP lease.
01202  *
01203  * @param netif network interface which must rebind with a DHCP server
01204  */
01205 static err_t
01206 dhcp_rebind(struct netif *netif)
01207 {
01208   struct dhcp *dhcp = netif_dhcp_data(netif);
01209   err_t result;
01210   u16_t msecs;
01211   u8_t i;
01212   struct pbuf *p_out;
01213   u16_t options_out_len;
01214 
01215   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind()\n"));
01216   dhcp_set_state(dhcp, DHCP_STATE_REBINDING);
01217 
01218   /* create and initialize the DHCP message header */
01219   p_out = dhcp_create_msg(netif, dhcp, DHCP_REQUEST, &options_out_len);
01220   if (p_out != NULL) {
01221     struct dhcp_msg *msg_out = (struct dhcp_msg *)p_out->payload;
01222     options_out_len = dhcp_option(options_out_len, msg_out->options, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
01223     options_out_len = dhcp_option_short(options_out_len, msg_out->options, DHCP_MAX_MSG_LEN(netif));
01224 
01225     options_out_len = dhcp_option(options_out_len, msg_out->options, DHCP_OPTION_PARAMETER_REQUEST_LIST, LWIP_ARRAYSIZE(dhcp_discover_request_options));
01226     for (i = 0; i < LWIP_ARRAYSIZE(dhcp_discover_request_options); i++) {
01227       options_out_len = dhcp_option_byte(options_out_len, msg_out->options, dhcp_discover_request_options[i]);
01228     }
01229 
01230 #if LWIP_NETIF_HOSTNAME
01231     options_out_len = dhcp_option_hostname(options_out_len, msg_out->options, netif);
01232 #endif /* LWIP_NETIF_HOSTNAME */
01233 
01234     LWIP_HOOK_DHCP_APPEND_OPTIONS(netif, dhcp, DHCP_STATE_REBINDING, msg_out, DHCP_DISCOVER, &options_out_len);
01235     dhcp_option_trailer(options_out_len, msg_out->options, p_out);
01236 
01237     /* broadcast to server */
01238     result = udp_sendto_if(dhcp_pcb, p_out, IP_ADDR_BROADCAST, LWIP_IANA_PORT_DHCP_SERVER, netif);
01239     pbuf_free(p_out);
01240     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind: REBINDING\n"));
01241   } else {
01242     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_rebind: could not allocate DHCP request\n"));
01243     result = ERR_MEM;
01244   }
01245   if (dhcp->tries < 255) {
01246     dhcp->tries++;
01247   }
01248   msecs = (u16_t)(dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000);
01249   dhcp->request_timeout = (u16_t)((msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS);
01250   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind(): set request timeout %"U16_F" msecs\n", msecs));
01251   return result;
01252 }
01253 
01254 /**
01255  * Enter REBOOTING state to verify an existing lease
01256  *
01257  * @param netif network interface which must reboot
01258  */
01259 static err_t
01260 dhcp_reboot(struct netif *netif)
01261 {
01262   struct dhcp *dhcp = netif_dhcp_data(netif);
01263   err_t result;
01264   u16_t msecs;
01265   u8_t i;
01266   struct pbuf *p_out;
01267   u16_t options_out_len;
01268 
01269   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot()\n"));
01270   dhcp_set_state(dhcp, DHCP_STATE_REBOOTING);
01271 
01272   /* create and initialize the DHCP message header */
01273   p_out = dhcp_create_msg(netif, dhcp, DHCP_REQUEST, &options_out_len);
01274   if (p_out != NULL) {
01275     struct dhcp_msg *msg_out = (struct dhcp_msg *)p_out->payload;
01276     options_out_len = dhcp_option(options_out_len, msg_out->options, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN);
01277     options_out_len = dhcp_option_short(options_out_len, msg_out->options, DHCP_MAX_MSG_LEN_MIN_REQUIRED);
01278 
01279     options_out_len = dhcp_option(options_out_len, msg_out->options, DHCP_OPTION_REQUESTED_IP, 4);
01280     options_out_len = dhcp_option_long(options_out_len, msg_out->options, lwip_ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr)));
01281 
01282     options_out_len = dhcp_option(options_out_len, msg_out->options, DHCP_OPTION_PARAMETER_REQUEST_LIST, LWIP_ARRAYSIZE(dhcp_discover_request_options));
01283     for (i = 0; i < LWIP_ARRAYSIZE(dhcp_discover_request_options); i++) {
01284       options_out_len = dhcp_option_byte(options_out_len, msg_out->options, dhcp_discover_request_options[i]);
01285     }
01286 
01287 #if LWIP_NETIF_HOSTNAME
01288     options_out_len = dhcp_option_hostname(options_out_len, msg_out->options, netif);
01289 #endif /* LWIP_NETIF_HOSTNAME */
01290 
01291     LWIP_HOOK_DHCP_APPEND_OPTIONS(netif, dhcp, DHCP_STATE_REBOOTING, msg_out, DHCP_REQUEST, &options_out_len);
01292     dhcp_option_trailer(options_out_len, msg_out->options, p_out);
01293 
01294     /* broadcast to server */
01295     result = udp_sendto_if(dhcp_pcb, p_out, IP_ADDR_BROADCAST, LWIP_IANA_PORT_DHCP_SERVER, netif);
01296     pbuf_free(p_out);
01297     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot: REBOOTING\n"));
01298   } else {
01299     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_reboot: could not allocate DHCP request\n"));
01300     result = ERR_MEM;
01301   }
01302   if (dhcp->tries < 255) {
01303     dhcp->tries++;
01304   }
01305   msecs = (u16_t)(dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000);
01306   dhcp->request_timeout = (u16_t)((msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS);
01307   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot(): set request timeout %"U16_F" msecs\n", msecs));
01308   return result;
01309 }
01310 
01311 /**
01312  * @ingroup dhcp4
01313  * Release a DHCP lease and stop DHCP statemachine (and AUTOIP if LWIP_DHCP_AUTOIP_COOP).
01314  *
01315  * @param netif network interface
01316  */
01317 void
01318 dhcp_release_and_stop(struct netif *netif)
01319 {
01320   struct dhcp *dhcp = netif_dhcp_data(netif);
01321   ip_addr_t server_ip_addr;
01322 
01323   LWIP_ASSERT_CORE_LOCKED();
01324   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_release_and_stop()\n"));
01325   if (dhcp == NULL) {
01326     return;
01327   }
01328 
01329   /* already off? -> nothing to do */
01330   if (dhcp->state == DHCP_STATE_OFF) {
01331     return;
01332   }
01333 
01334   ip_addr_copy(server_ip_addr, dhcp->server_ip_addr);
01335 
01336   /* clean old DHCP offer */
01337   ip_addr_set_zero_ip4(&dhcp->server_ip_addr);
01338   ip4_addr_set_zero(&dhcp->offered_ip_addr);
01339   ip4_addr_set_zero(&dhcp->offered_sn_mask);
01340   ip4_addr_set_zero(&dhcp->offered_gw_addr);
01341 #if LWIP_DHCP_BOOTP_FILE
01342   ip4_addr_set_zero(&dhcp->offered_si_addr);
01343 #endif /* LWIP_DHCP_BOOTP_FILE */
01344   dhcp->offered_t0_lease = dhcp->offered_t1_renew = dhcp->offered_t2_rebind = 0;
01345   dhcp->t1_renew_time = dhcp->t2_rebind_time = dhcp->lease_used = dhcp->t0_timeout = 0;
01346 
01347   /* send release message when current IP was assigned via DHCP */
01348   if (dhcp_supplied_address(netif)) {
01349     /* create and initialize the DHCP message header */
01350     struct pbuf *p_out;
01351     u16_t options_out_len;
01352     p_out = dhcp_create_msg(netif, dhcp, DHCP_RELEASE, &options_out_len);
01353     if (p_out != NULL) {
01354       struct dhcp_msg *msg_out = (struct dhcp_msg *)p_out->payload;
01355       options_out_len = dhcp_option(options_out_len, msg_out->options, DHCP_OPTION_SERVER_ID, 4);
01356       options_out_len = dhcp_option_long(options_out_len, msg_out->options, lwip_ntohl(ip4_addr_get_u32(ip_2_ip4(&server_ip_addr))));
01357 
01358       LWIP_HOOK_DHCP_APPEND_OPTIONS(netif, dhcp, dhcp->state, msg_out, DHCP_RELEASE, &options_out_len);
01359       dhcp_option_trailer(options_out_len, msg_out->options, p_out);
01360 
01361       udp_sendto_if(dhcp_pcb, p_out, &server_ip_addr, LWIP_IANA_PORT_DHCP_SERVER, netif);
01362       pbuf_free(p_out);
01363       LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_release: RELEASED, DHCP_STATE_OFF\n"));
01364     } else {
01365       /* sending release failed, but that's not a problem since the correct behaviour of dhcp does not rely on release */
01366       LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_release: could not allocate DHCP request\n"));
01367     }
01368   }
01369 
01370   /* remove IP address from interface (prevents routing from selecting this interface) */
01371   netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4);
01372 
01373 #if LWIP_DHCP_AUTOIP_COOP
01374   if (dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) {
01375     autoip_stop(netif);
01376     dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF;
01377   }
01378 #endif /* LWIP_DHCP_AUTOIP_COOP */
01379 
01380   dhcp_set_state(dhcp, DHCP_STATE_OFF);
01381 
01382   if (dhcp->pcb_allocated != 0) {
01383     dhcp_dec_pcb_refcount(); /* free DHCP PCB if not needed any more */
01384     dhcp->pcb_allocated = 0;
01385   }
01386 }
01387 
01388 /**
01389  * @ingroup dhcp4
01390  * This function calls dhcp_release_and_stop() internally.
01391  * @deprecated Use dhcp_release_and_stop() instead.
01392  */
01393 err_t
01394 dhcp_release(struct netif *netif)
01395 {
01396   dhcp_release_and_stop(netif);
01397   return ERR_OK;
01398 }
01399 
01400 /**
01401  * @ingroup dhcp4
01402  * This function calls dhcp_release_and_stop() internally.
01403  * @deprecated Use dhcp_release_and_stop() instead.
01404  */
01405 void
01406 dhcp_stop(struct netif *netif)
01407 {
01408   dhcp_release_and_stop(netif);
01409 }
01410 
01411 /*
01412  * Set the DHCP state of a DHCP client.
01413  *
01414  * If the state changed, reset the number of tries.
01415  */
01416 static void
01417 dhcp_set_state(struct dhcp *dhcp, u8_t new_state)
01418 {
01419   if (new_state != dhcp->state) {
01420     dhcp->state = new_state;
01421     dhcp->tries = 0;
01422     dhcp->request_timeout = 0;
01423   }
01424 }
01425 
01426 /*
01427  * Concatenate an option type and length field to the outgoing
01428  * DHCP message.
01429  *
01430  */
01431 static u16_t
01432 dhcp_option(u16_t options_out_len, u8_t *options, u8_t option_type, u8_t option_len)
01433 {
01434   LWIP_ASSERT("dhcp_option: options_out_len + 2 + option_len <= DHCP_OPTIONS_LEN", options_out_len + 2U + option_len <= DHCP_OPTIONS_LEN);
01435   options[options_out_len++] = option_type;
01436   options[options_out_len++] = option_len;
01437   return options_out_len;
01438 }
01439 /*
01440  * Concatenate a single byte to the outgoing DHCP message.
01441  *
01442  */
01443 static u16_t
01444 dhcp_option_byte(u16_t options_out_len, u8_t *options, u8_t value)
01445 {
01446   LWIP_ASSERT("dhcp_option_byte: options_out_len < DHCP_OPTIONS_LEN", options_out_len < DHCP_OPTIONS_LEN);
01447   options[options_out_len++] = value;
01448   return options_out_len;
01449 }
01450 
01451 static u16_t
01452 dhcp_option_short(u16_t options_out_len, u8_t *options, u16_t value)
01453 {
01454   LWIP_ASSERT("dhcp_option_short: options_out_len + 2 <= DHCP_OPTIONS_LEN", options_out_len + 2U <= DHCP_OPTIONS_LEN);
01455   options[options_out_len++] = (u8_t)((value & 0xff00U) >> 8);
01456   options[options_out_len++] = (u8_t) (value & 0x00ffU);
01457   return options_out_len;
01458 }
01459 
01460 static u16_t
01461 dhcp_option_long(u16_t options_out_len, u8_t *options, u32_t value)
01462 {
01463   LWIP_ASSERT("dhcp_option_long: options_out_len + 4 <= DHCP_OPTIONS_LEN", options_out_len + 4U <= DHCP_OPTIONS_LEN);
01464   options[options_out_len++] = (u8_t)((value & 0xff000000UL) >> 24);
01465   options[options_out_len++] = (u8_t)((value & 0x00ff0000UL) >> 16);
01466   options[options_out_len++] = (u8_t)((value & 0x0000ff00UL) >> 8);
01467   options[options_out_len++] = (u8_t)((value & 0x000000ffUL));
01468   return options_out_len;
01469 }
01470 
01471 #if LWIP_NETIF_HOSTNAME
01472 static u16_t
01473 dhcp_option_hostname(u16_t options_out_len, u8_t *options, struct netif *netif)
01474 {
01475   if (netif->hostname != NULL) {
01476     size_t namelen = strlen(netif->hostname);
01477     if (namelen > 0) {
01478       size_t len;
01479       const char *p = netif->hostname;
01480       /* Shrink len to available bytes (need 2 bytes for OPTION_HOSTNAME
01481          and 1 byte for trailer) */
01482       size_t available = DHCP_OPTIONS_LEN - options_out_len - 3;
01483       LWIP_ASSERT("DHCP: hostname is too long!", namelen <= available);
01484       len = LWIP_MIN(namelen, available);
01485       LWIP_ASSERT("DHCP: hostname is too long!", len <= 0xFF);
01486       options_out_len = dhcp_option(options_out_len, options, DHCP_OPTION_HOSTNAME, (u8_t)len);
01487       while (len--) {
01488         options_out_len = dhcp_option_byte(options_out_len, options, *p++);
01489       }
01490     }
01491   }
01492   return options_out_len;
01493 }
01494 #endif /* LWIP_NETIF_HOSTNAME */
01495 
01496 /**
01497  * Extract the DHCP message and the DHCP options.
01498  *
01499  * Extract the DHCP message and the DHCP options, each into a contiguous
01500  * piece of memory. As a DHCP message is variable sized by its options,
01501  * and also allows overriding some fields for options, the easy approach
01502  * is to first unfold the options into a contiguous piece of memory, and
01503  * use that further on.
01504  *
01505  */
01506 static err_t
01507 dhcp_parse_reply(struct pbuf *p, struct dhcp *dhcp)
01508 {
01509   u8_t *options;
01510   u16_t offset;
01511   u16_t offset_max;
01512   u16_t options_idx;
01513   u16_t options_idx_max;
01514   struct pbuf *q;
01515   int parse_file_as_options = 0;
01516   int parse_sname_as_options = 0;
01517   struct dhcp_msg *msg_in;
01518 #if LWIP_DHCP_BOOTP_FILE
01519   int file_overloaded = 0;
01520 #endif
01521 
01522   LWIP_UNUSED_ARG(dhcp);
01523 
01524   /* clear received options */
01525   dhcp_clear_all_options(dhcp);
01526   /* check that beginning of dhcp_msg (up to and including chaddr) is in first pbuf */
01527   if (p->len < DHCP_SNAME_OFS) {
01528     return ERR_BUF;
01529   }
01530   msg_in = (struct dhcp_msg *)p->payload;
01531 #if LWIP_DHCP_BOOTP_FILE
01532   /* clear boot file name */
01533   dhcp->boot_file_name[0] = 0;
01534 #endif /* LWIP_DHCP_BOOTP_FILE */
01535 
01536   /* parse options */
01537 
01538   /* start with options field */
01539   options_idx = DHCP_OPTIONS_OFS;
01540   /* parse options to the end of the received packet */
01541   options_idx_max = p->tot_len;
01542 again:
01543   q = p;
01544   while ((q != NULL) && (options_idx >= q->len)) {
01545     options_idx = (u16_t)(options_idx - q->len);
01546     options_idx_max = (u16_t)(options_idx_max - q->len);
01547     q = q->next;
01548   }
01549   if (q == NULL) {
01550     return ERR_BUF;
01551   }
01552   offset = options_idx;
01553   offset_max = options_idx_max;
01554   options = (u8_t *)q->payload;
01555   /* at least 1 byte to read and no end marker, then at least 3 bytes to read? */
01556   while ((q != NULL) && (offset < offset_max) && (options[offset] != DHCP_OPTION_END)) {
01557     u8_t op = options[offset];
01558     u8_t len;
01559     u8_t decode_len = 0;
01560     int decode_idx = -1;
01561     u16_t val_offset = (u16_t)(offset + 2);
01562     if (val_offset < offset) {
01563       /* overflow */
01564       return ERR_BUF;
01565     }
01566     /* len byte might be in the next pbuf */
01567     if ((offset + 1) < q->len) {
01568       len = options[offset + 1];
01569     } else {
01570       len = (q->next != NULL ? ((u8_t *)q->next->payload)[0] : 0);
01571     }
01572     /* LWIP_DEBUGF(DHCP_DEBUG, ("msg_offset=%"U16_F", q->len=%"U16_F, msg_offset, q->len)); */
01573     decode_len = len;
01574     switch (op) {
01575       /* case(DHCP_OPTION_END): handled above */
01576       case (DHCP_OPTION_PAD):
01577         /* special option: no len encoded */
01578         decode_len = len = 0;
01579         /* will be increased below */
01580         break;
01581       case (DHCP_OPTION_SUBNET_MASK):
01582         LWIP_ERROR("len == 4", len == 4, return ERR_VAL;);
01583         decode_idx = DHCP_OPTION_IDX_SUBNET_MASK;
01584         break;
01585       case (DHCP_OPTION_ROUTER):
01586         decode_len = 4; /* only copy the first given router */
01587         LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;);
01588         decode_idx = DHCP_OPTION_IDX_ROUTER;
01589         break;
01590 #if LWIP_DHCP_PROVIDE_DNS_SERVERS
01591       case (DHCP_OPTION_DNS_SERVER):
01592         /* special case: there might be more than one server */
01593         LWIP_ERROR("len %% 4 == 0", len % 4 == 0, return ERR_VAL;);
01594         /* limit number of DNS servers */
01595         decode_len = LWIP_MIN(len, 4 * DNS_MAX_SERVERS);
01596         LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;);
01597         decode_idx = DHCP_OPTION_IDX_DNS_SERVER;
01598         break;
01599 #endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS */
01600       case (DHCP_OPTION_LEASE_TIME):
01601         LWIP_ERROR("len == 4", len == 4, return ERR_VAL;);
01602         decode_idx = DHCP_OPTION_IDX_LEASE_TIME;
01603         break;
01604 #if LWIP_DHCP_GET_NTP_SRV
01605       case (DHCP_OPTION_NTP):
01606         /* special case: there might be more than one server */
01607         LWIP_ERROR("len %% 4 == 0", len % 4 == 0, return ERR_VAL;);
01608         /* limit number of NTP servers */
01609         decode_len = LWIP_MIN(len, 4 * LWIP_DHCP_MAX_NTP_SERVERS);
01610         LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;);
01611         decode_idx = DHCP_OPTION_IDX_NTP_SERVER;
01612         break;
01613 #endif /* LWIP_DHCP_GET_NTP_SRV*/
01614       case (DHCP_OPTION_OVERLOAD):
01615         LWIP_ERROR("len == 1", len == 1, return ERR_VAL;);
01616         /* decode overload only in options, not in file/sname: invalid packet */
01617         LWIP_ERROR("overload in file/sname", options_idx == DHCP_OPTIONS_OFS, return ERR_VAL;);
01618         decode_idx = DHCP_OPTION_IDX_OVERLOAD;
01619         break;
01620       case (DHCP_OPTION_MESSAGE_TYPE):
01621         LWIP_ERROR("len == 1", len == 1, return ERR_VAL;);
01622         decode_idx = DHCP_OPTION_IDX_MSG_TYPE;
01623         break;
01624       case (DHCP_OPTION_SERVER_ID):
01625         LWIP_ERROR("len == 4", len == 4, return ERR_VAL;);
01626         decode_idx = DHCP_OPTION_IDX_SERVER_ID;
01627         break;
01628       case (DHCP_OPTION_T1):
01629         LWIP_ERROR("len == 4", len == 4, return ERR_VAL;);
01630         decode_idx = DHCP_OPTION_IDX_T1;
01631         break;
01632       case (DHCP_OPTION_T2):
01633         LWIP_ERROR("len == 4", len == 4, return ERR_VAL;);
01634         decode_idx = DHCP_OPTION_IDX_T2;
01635         break;
01636       default:
01637         decode_len = 0;
01638         LWIP_DEBUGF(DHCP_DEBUG, ("skipping option %"U16_F" in options\n", (u16_t)op));
01639         LWIP_HOOK_DHCP_PARSE_OPTION(ip_current_netif(), dhcp, dhcp->state, msg_in,
01640                                     dhcp_option_given(dhcp, DHCP_OPTION_IDX_MSG_TYPE) ? (u8_t)dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_MSG_TYPE) : 0,
01641                                     op, len, q, val_offset);
01642         break;
01643     }
01644     if (op == DHCP_OPTION_PAD) {
01645       offset++;
01646     } else {
01647       if (offset + len + 2 > 0xFFFF) {
01648         /* overflow */
01649         return ERR_BUF;
01650       }
01651       offset = (u16_t)(offset + len + 2);
01652       if (decode_len > 0) {
01653         u32_t value = 0;
01654         u16_t copy_len;
01655 decode_next:
01656         LWIP_ASSERT("check decode_idx", decode_idx >= 0 && decode_idx < DHCP_OPTION_IDX_MAX);
01657         if (!dhcp_option_given(dhcp, decode_idx)) {
01658           copy_len = LWIP_MIN(decode_len, 4);
01659           if (pbuf_copy_partial(q, &value, copy_len, val_offset) != copy_len) {
01660             return ERR_BUF;
01661           }
01662           if (decode_len > 4) {
01663             /* decode more than one u32_t */
01664             u16_t next_val_offset;
01665             LWIP_ERROR("decode_len %% 4 == 0", decode_len % 4 == 0, return ERR_VAL;);
01666             dhcp_got_option(dhcp, decode_idx);
01667             dhcp_set_option_value(dhcp, decode_idx, lwip_htonl(value));
01668             decode_len = (u8_t)(decode_len - 4);
01669             next_val_offset = (u16_t)(val_offset + 4);
01670             if (next_val_offset < val_offset) {
01671               /* overflow */
01672               return ERR_BUF;
01673             }
01674             val_offset = next_val_offset;
01675             decode_idx++;
01676             goto decode_next;
01677           } else if (decode_len == 4) {
01678             value = lwip_ntohl(value);
01679           } else {
01680             LWIP_ERROR("invalid decode_len", decode_len == 1, return ERR_VAL;);
01681             value = ((u8_t *)&value)[0];
01682           }
01683           dhcp_got_option(dhcp, decode_idx);
01684           dhcp_set_option_value(dhcp, decode_idx, value);
01685         }
01686       }
01687     }
01688     if (offset >= q->len) {
01689       offset = (u16_t)(offset - q->len);
01690       offset_max = (u16_t)(offset_max - q->len);
01691       if (offset < offset_max) {
01692         q = q->next;
01693         LWIP_ERROR("next pbuf was null", q != NULL, return ERR_VAL;);
01694         options = (u8_t *)q->payload;
01695       } else {
01696         /* We've run out of bytes, probably no end marker. Don't proceed. */
01697         return ERR_BUF;
01698       }
01699     }
01700   }
01701   /* is this an overloaded message? */
01702   if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_OVERLOAD)) {
01703     u32_t overload = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_OVERLOAD);
01704     dhcp_clear_option(dhcp, DHCP_OPTION_IDX_OVERLOAD);
01705     if (overload == DHCP_OVERLOAD_FILE) {
01706       parse_file_as_options = 1;
01707       LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded file field\n"));
01708     } else if (overload == DHCP_OVERLOAD_SNAME) {
01709       parse_sname_as_options = 1;
01710       LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded sname field\n"));
01711     } else if (overload == DHCP_OVERLOAD_SNAME_FILE) {
01712       parse_sname_as_options = 1;
01713       parse_file_as_options = 1;
01714       LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded sname and file field\n"));
01715     } else {
01716       LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("invalid overload option: %d\n", (int)overload));
01717     }
01718   }
01719   if (parse_file_as_options) {
01720     /* if both are overloaded, parse file first and then sname (RFC 2131 ch. 4.1) */
01721     parse_file_as_options = 0;
01722     options_idx = DHCP_FILE_OFS;
01723     options_idx_max = DHCP_FILE_OFS + DHCP_FILE_LEN;
01724 #if LWIP_DHCP_BOOTP_FILE
01725     file_overloaded = 1;
01726 #endif
01727     goto again;
01728   } else if (parse_sname_as_options) {
01729     parse_sname_as_options = 0;
01730     options_idx = DHCP_SNAME_OFS;
01731     options_idx_max = DHCP_SNAME_OFS + DHCP_SNAME_LEN;
01732     goto again;
01733   }
01734 #if LWIP_DHCP_BOOTP_FILE
01735   if (!file_overloaded) {
01736     /* only do this for ACK messages */
01737     if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_MSG_TYPE) &&
01738       (dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_MSG_TYPE) == DHCP_ACK))
01739     /* copy bootp file name, don't care for sname (server hostname) */
01740     if (pbuf_copy_partial(p, dhcp->boot_file_name, DHCP_FILE_LEN-1, DHCP_FILE_OFS) != (DHCP_FILE_LEN-1)) {
01741       return ERR_BUF;
01742     }
01743     /* make sure the string is really NULL-terminated */
01744     dhcp->boot_file_name[DHCP_FILE_LEN-1] = 0;
01745   }
01746 #endif /* LWIP_DHCP_BOOTP_FILE */ 
01747   return ERR_OK;
01748 }
01749 
01750 /**
01751  * If an incoming DHCP message is in response to us, then trigger the state machine
01752  */
01753 static void
01754 dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
01755 {
01756   struct netif *netif = ip_current_input_netif();
01757   struct dhcp *dhcp = netif_dhcp_data(netif);
01758   struct dhcp_msg *reply_msg = (struct dhcp_msg *)p->payload;
01759   u8_t msg_type;
01760   u8_t i;
01761   struct dhcp_msg *msg_in;
01762 
01763   LWIP_UNUSED_ARG(arg);
01764 
01765   /* Caught DHCP message from netif that does not have DHCP enabled? -> not interested */
01766   if ((dhcp == NULL) || (dhcp->pcb_allocated == 0)) {
01767     goto free_pbuf_and_return;
01768   }
01769 
01770   LWIP_ASSERT("invalid server address type", IP_IS_V4(addr));
01771 
01772   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_recv(pbuf = %p) from DHCP server %"U16_F".%"U16_F".%"U16_F".%"U16_F" port %"U16_F"\n", (void *)p,
01773               ip4_addr1_16(ip_2_ip4(addr)), ip4_addr2_16(ip_2_ip4(addr)), ip4_addr3_16(ip_2_ip4(addr)), ip4_addr4_16(ip_2_ip4(addr)), port));
01774   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("pbuf->len = %"U16_F"\n", p->len));
01775   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("pbuf->tot_len = %"U16_F"\n", p->tot_len));
01776   /* prevent warnings about unused arguments */
01777   LWIP_UNUSED_ARG(pcb);
01778   LWIP_UNUSED_ARG(addr);
01779   LWIP_UNUSED_ARG(port);
01780 
01781   if (p->len < DHCP_MIN_REPLY_LEN) {
01782     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("DHCP reply message or pbuf too short\n"));
01783     goto free_pbuf_and_return;
01784   }
01785 
01786   if (reply_msg->op != DHCP_BOOTREPLY) {
01787     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("not a DHCP reply message, but type %"U16_F"\n", (u16_t)reply_msg->op));
01788     goto free_pbuf_and_return;
01789   }
01790   /* iterate through hardware address and match against DHCP message */
01791   for (i = 0; i < netif->hwaddr_len && i < LWIP_MIN(DHCP_CHADDR_LEN, NETIF_MAX_HWADDR_LEN); i++) {
01792     if (netif->hwaddr[i] != reply_msg->chaddr[i]) {
01793       LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
01794                   ("netif->hwaddr[%"U16_F"]==%02"X16_F" != reply_msg->chaddr[%"U16_F"]==%02"X16_F"\n",
01795                    (u16_t)i, (u16_t)netif->hwaddr[i], (u16_t)i, (u16_t)reply_msg->chaddr[i]));
01796       goto free_pbuf_and_return;
01797     }
01798   }
01799   /* match transaction ID against what we expected */
01800   if (lwip_ntohl(reply_msg->xid) != dhcp->xid) {
01801     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
01802                 ("transaction id mismatch reply_msg->xid(%"X32_F")!=dhcp->xid(%"X32_F")\n", lwip_ntohl(reply_msg->xid), dhcp->xid));
01803     goto free_pbuf_and_return;
01804   }
01805   /* option fields could be unfold? */
01806   if (dhcp_parse_reply(p, dhcp) != ERR_OK) {
01807     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
01808                 ("problem unfolding DHCP message - too short on memory?\n"));
01809     goto free_pbuf_and_return;
01810   }
01811 
01812   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("searching DHCP_OPTION_MESSAGE_TYPE\n"));
01813   /* obtain pointer to DHCP message type */
01814   if (!dhcp_option_given(dhcp, DHCP_OPTION_IDX_MSG_TYPE)) {
01815     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("DHCP_OPTION_MESSAGE_TYPE option not found\n"));
01816     goto free_pbuf_and_return;
01817   }
01818 
01819   msg_in = (struct dhcp_msg *)p->payload;
01820   /* read DHCP message type */
01821   msg_type = (u8_t)dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_MSG_TYPE);
01822   /* message type is DHCP ACK? */
01823   if (msg_type == DHCP_ACK) {
01824     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_ACK received\n"));
01825     /* in requesting state? */
01826     if (dhcp->state == DHCP_STATE_REQUESTING) {
01827       dhcp_handle_ack(netif, msg_in);
01828 #if DHCP_DOES_ARP_CHECK
01829       if ((netif->flags & NETIF_FLAG_ETHARP) != 0) {
01830         /* check if the acknowledged lease address is already in use */
01831         dhcp_check(netif);
01832       } else {
01833         /* bind interface to the acknowledged lease address */
01834         dhcp_bind(netif);
01835       }
01836 #else
01837       /* bind interface to the acknowledged lease address */
01838       dhcp_bind(netif);
01839 #endif
01840     }
01841     /* already bound to the given lease address? */
01842     else if ((dhcp->state == DHCP_STATE_REBOOTING) || (dhcp->state == DHCP_STATE_REBINDING) ||
01843              (dhcp->state == DHCP_STATE_RENEWING)) {
01844       dhcp_handle_ack(netif, msg_in);
01845       dhcp_bind(netif);
01846     }
01847   }
01848   /* received a DHCP_NAK in appropriate state? */
01849   else if ((msg_type == DHCP_NAK) &&
01850            ((dhcp->state == DHCP_STATE_REBOOTING) || (dhcp->state == DHCP_STATE_REQUESTING) ||
01851             (dhcp->state == DHCP_STATE_REBINDING) || (dhcp->state == DHCP_STATE_RENEWING  ))) {
01852     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_NAK received\n"));
01853     dhcp_handle_nak(netif);
01854   }
01855   /* received a DHCP_OFFER in DHCP_STATE_SELECTING state? */
01856   else if ((msg_type == DHCP_OFFER) && (dhcp->state == DHCP_STATE_SELECTING)) {
01857     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_OFFER received in DHCP_STATE_SELECTING state\n"));
01858     /* remember offered lease */
01859     dhcp_handle_offer(netif, msg_in);
01860   }
01861 
01862 free_pbuf_and_return:
01863   pbuf_free(p);
01864 }
01865 
01866 /**
01867  * Create a DHCP request, fill in common headers
01868  *
01869  * @param netif the netif under DHCP control
01870  * @param dhcp dhcp control struct
01871  * @param message_type message type of the request
01872  */
01873 static struct pbuf *
01874 dhcp_create_msg(struct netif *netif, struct dhcp *dhcp, u8_t message_type, u16_t *options_out_len)
01875 {
01876   u16_t i;
01877   struct pbuf *p_out;
01878   struct dhcp_msg *msg_out;
01879   u16_t options_out_len_loc;
01880 
01881 #ifndef DHCP_GLOBAL_XID
01882   /** default global transaction identifier starting value (easy to match
01883    *  with a packet analyser). We simply increment for each new request.
01884    *  Predefine DHCP_GLOBAL_XID to a better value or a function call to generate one
01885    *  at runtime, any supporting function prototypes can be defined in DHCP_GLOBAL_XID_HEADER */
01886 #if DHCP_CREATE_RAND_XID && defined(LWIP_RAND)
01887   static u32_t xid;
01888 #else /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */
01889   static u32_t xid = 0xABCD0000;
01890 #endif /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */
01891 #else
01892   if (!xid_initialised) {
01893     xid = DHCP_GLOBAL_XID;
01894     xid_initialised = !xid_initialised;
01895   }
01896 #endif
01897   LWIP_ERROR("dhcp_create_msg: netif != NULL", (netif != NULL), return NULL;);
01898   LWIP_ERROR("dhcp_create_msg: dhcp != NULL", (dhcp != NULL), return NULL;);
01899   p_out = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcp_msg), PBUF_RAM);
01900   if (p_out == NULL) {
01901     LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
01902                 ("dhcp_create_msg(): could not allocate pbuf\n"));
01903     return NULL;
01904   }
01905   LWIP_ASSERT("dhcp_create_msg: check that first pbuf can hold struct dhcp_msg",
01906               (p_out->len >= sizeof(struct dhcp_msg)));
01907 
01908   /* DHCP_REQUEST should reuse 'xid' from DHCPOFFER */
01909   if ((message_type != DHCP_REQUEST) || (dhcp->state == DHCP_STATE_REBOOTING)) {
01910     /* reuse transaction identifier in retransmissions */
01911     if (dhcp->tries == 0) {
01912 #if DHCP_CREATE_RAND_XID && defined(LWIP_RAND)
01913       xid = LWIP_RAND();
01914 #else /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */
01915       xid++;
01916 #endif /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */
01917     }
01918     dhcp->xid = xid;
01919   }
01920   LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE,
01921               ("transaction id xid(%"X32_F")\n", xid));
01922 
01923   msg_out = (struct dhcp_msg *)p_out->payload;
01924   memset(msg_out, 0, sizeof(struct dhcp_msg));
01925 
01926   msg_out->op = DHCP_BOOTREQUEST;
01927   /* @todo: make link layer independent */
01928   msg_out->htype = LWIP_IANA_HWTYPE_ETHERNET;
01929   msg_out->hlen = netif->hwaddr_len;
01930   msg_out->xid = lwip_htonl(dhcp->xid);
01931   /* we don't need the broadcast flag since we can receive unicast traffic
01932      before being fully configured! */
01933   /* set ciaddr to netif->ip_addr based on message_type and state */
01934   if ((message_type == DHCP_INFORM) || (message_type == DHCP_DECLINE) || (message_type == DHCP_RELEASE) ||
01935       ((message_type == DHCP_REQUEST) && /* DHCP_STATE_BOUND not used for sending! */
01936        ((dhcp->state == DHCP_STATE_RENEWING) || dhcp->state == DHCP_STATE_REBINDING))) {
01937     ip4_addr_copy(msg_out->ciaddr, *netif_ip4_addr(netif));
01938   }
01939   for (i = 0; i < LWIP_MIN(DHCP_CHADDR_LEN, NETIF_MAX_HWADDR_LEN); i++) {
01940     /* copy netif hardware address (padded with zeroes through memset already) */
01941     msg_out->chaddr[i] = netif->hwaddr[i];
01942   }
01943   msg_out->cookie = PP_HTONL(DHCP_MAGIC_COOKIE);
01944   /* Add option MESSAGE_TYPE */
01945   options_out_len_loc = dhcp_option(0, msg_out->options, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN);
01946   options_out_len_loc = dhcp_option_byte(options_out_len_loc, msg_out->options, message_type);
01947   if (options_out_len) {
01948     *options_out_len = options_out_len_loc;
01949   }
01950   return p_out;
01951 }
01952 
01953 /**
01954  * Add a DHCP message trailer
01955  *
01956  * Adds the END option to the DHCP message, and if
01957  * necessary, up to three padding bytes.
01958  */
01959 static void
01960 dhcp_option_trailer(u16_t options_out_len, u8_t *options, struct pbuf *p_out)
01961 {
01962   options[options_out_len++] = DHCP_OPTION_END;
01963   /* packet is too small, or not 4 byte aligned? */
01964   while (((options_out_len < DHCP_MIN_OPTIONS_LEN) || (options_out_len & 3)) &&
01965          (options_out_len < DHCP_OPTIONS_LEN)) {
01966     /* add a fill/padding byte */
01967     options[options_out_len++] = 0;
01968   }
01969   /* shrink the pbuf to the actual content length */
01970   pbuf_realloc(p_out, (u16_t)(sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + options_out_len));
01971 }
01972 
01973 /** check if DHCP supplied netif->ip_addr
01974  *
01975  * @param netif the netif to check
01976  * @return 1 if DHCP supplied netif->ip_addr (states BOUND or RENEWING),
01977  *         0 otherwise
01978  */
01979 u8_t
01980 dhcp_supplied_address(const struct netif *netif)
01981 {
01982   if ((netif != NULL) && (netif_dhcp_data(netif) != NULL)) {
01983     struct dhcp *dhcp = netif_dhcp_data(netif);
01984     return (dhcp->state == DHCP_STATE_BOUND) || (dhcp->state == DHCP_STATE_RENEWING) ||
01985            (dhcp->state == DHCP_STATE_REBINDING);
01986   }
01987   return 0;
01988 }
01989 
01990 #endif /* LWIP_IPV4 && LWIP_DHCP */