Port of LwIP performed by Ralf in 2010. Not recommended for use with recent mbed libraries, but good demos of raw LwIP possible

Dependents:   LwIP_raw_API_serverExample tiny-dtls

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