Ethernet for Nucleo and Disco board STM32F746 works with gcc and arm. IAC is untested

Dependents:   STM32F746_iothub_client_sample_mqtt DISCO-F746NG_Ethernet Nucleo_F746ZG_Ethernet thethingsiO-DISCO_F746NG-mqtt ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers dhcp.c Source File

dhcp.c

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