Example program with HTTPServer and sensor data streaming over TCPSockets, using Donatien Garnier's Net APIs and services code on top of LWIP. Files StreamServer.h and .cpp encapsulate streaming over TCPSockets. Broadcast is done by sendToAll(), and all incoming data is echoed back to the client. Echo code can be replaced with some remote control of the streaming interface. See main() that shows how to periodically send some data to all subscribed clients. To subscribe, a client should open a socket at <mbed_ip> port 123. I used few lines in TCL code to set up a quick sink for the data. HTTP files are served on port 80 concurrently to the streaming.

Dependencies:   mbed

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