Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
dhcp.c
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((n < DNS_MAX_SERVERS) && dhcp_option_given(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n)) { 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 /** Removes a struct dhcp from a netif. 00596 * 00597 * ATTENTION: Only use this when not using dhcp_set_struct() to allocate the 00598 * struct dhcp since the memory is passed back to the heap. 00599 * 00600 * @param netif the netif from which to remove the struct dhcp 00601 */ 00602 void dhcp_cleanup(struct netif *netif) 00603 { 00604 LWIP_ASSERT("netif != NULL", netif != NULL); 00605 00606 if (netif->dhcp != NULL) { 00607 mem_free(netif->dhcp); 00608 netif->dhcp = NULL; 00609 } 00610 } 00611 00612 /** 00613 * Start DHCP negotiation for a network interface. 00614 * 00615 * If no DHCP client instance was attached to this interface, 00616 * a new client is created first. If a DHCP client instance 00617 * was already present, it restarts negotiation. 00618 * 00619 * @param netif The lwIP network interface 00620 * @return lwIP error code 00621 * - ERR_OK - No error 00622 * - ERR_MEM - Out of memory 00623 */ 00624 err_t 00625 dhcp_start(struct netif *netif) 00626 { 00627 struct dhcp *dhcp; 00628 err_t result = ERR_OK; 00629 00630 LWIP_ERROR("netif != NULL", (netif != NULL), return ERR_ARG;); 00631 dhcp = netif->dhcp; 00632 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)); 00633 /* Remove the flag that says this netif is handled by DHCP, 00634 it is set when we succeeded starting. */ 00635 netif->flags &= ~NETIF_FLAG_DHCP; 00636 00637 /* check hwtype of the netif */ 00638 if ((netif->flags & NETIF_FLAG_ETHARP) == 0) { 00639 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): No ETHARP netif\n")); 00640 return ERR_ARG; 00641 } 00642 00643 /* check MTU of the netif */ 00644 if (netif->mtu < DHCP_MAX_MSG_LEN_MIN_REQUIRED) { 00645 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): Cannot use this netif with DHCP: MTU is too small\n")); 00646 return ERR_MEM; 00647 } 00648 00649 /* no DHCP client attached yet? */ 00650 if (dhcp == NULL) { 00651 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): starting new DHCP client\n")); 00652 dhcp = (struct dhcp *)mem_malloc(sizeof(struct dhcp)); 00653 if (dhcp == NULL) { 00654 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): could not allocate dhcp\n")); 00655 return ERR_MEM; 00656 } 00657 /* store this dhcp client in the netif */ 00658 netif->dhcp = dhcp; 00659 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): allocated dhcp")); 00660 /* already has DHCP client attached */ 00661 } else { 00662 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_start(): restarting DHCP configuration\n")); 00663 if (dhcp->pcb != NULL) { 00664 udp_remove(dhcp->pcb); 00665 } 00666 LWIP_ASSERT("pbuf p_out wasn't freed", dhcp->p_out == NULL); 00667 LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL ); 00668 } 00669 00670 /* clear data structure */ 00671 memset(dhcp, 0, sizeof(struct dhcp)); 00672 /* dhcp_set_state(&dhcp, DHCP_OFF); */ 00673 /* allocate UDP PCB */ 00674 dhcp->pcb = udp_new(); 00675 if (dhcp->pcb == NULL) { 00676 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): could not obtain pcb\n")); 00677 return ERR_MEM; 00678 } 00679 dhcp->pcb->so_options |= SOF_BROADCAST; 00680 /* set up local and remote port for the pcb */ 00681 udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT); 00682 udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT); 00683 /* set up the recv callback and argument */ 00684 udp_recv(dhcp->pcb, dhcp_recv, netif); 00685 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): starting DHCP configuration\n")); 00686 /* (re)start the DHCP negotiation */ 00687 result = dhcp_discover(netif); 00688 if (result != ERR_OK) { 00689 /* free resources allocated above */ 00690 dhcp_stop(netif); 00691 return ERR_MEM; 00692 } 00693 /* Set the flag that says this netif is handled by DHCP. */ 00694 netif->flags |= NETIF_FLAG_DHCP; 00695 return result; 00696 } 00697 00698 /** 00699 * Inform a DHCP server of our manual configuration. 00700 * 00701 * This informs DHCP servers of our fixed IP address configuration 00702 * by sending an INFORM message. It does not involve DHCP address 00703 * configuration, it is just here to be nice to the network. 00704 * 00705 * @param netif The lwIP network interface 00706 */ 00707 void 00708 dhcp_inform(struct netif *netif) 00709 { 00710 struct dhcp dhcp; 00711 err_t result = ERR_OK; 00712 struct udp_pcb *pcb; 00713 00714 LWIP_ERROR("netif != NULL", (netif != NULL), return;); 00715 00716 memset(&dhcp, 0, sizeof(struct dhcp)); 00717 dhcp_set_state(&dhcp, DHCP_INFORM); 00718 00719 if ((netif->dhcp != NULL) && (netif->dhcp->pcb != NULL)) { 00720 /* re-use existing pcb */ 00721 pcb = netif->dhcp->pcb; 00722 } else { 00723 pcb = udp_new(); 00724 if (pcb == NULL) { 00725 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_inform(): could not obtain pcb")); 00726 return; 00727 } 00728 dhcp.pcb = pcb; 00729 dhcp.pcb->so_options |= SOF_BROADCAST; 00730 udp_bind(dhcp.pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT); 00731 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_inform(): created new udp pcb\n")); 00732 } 00733 /* create and initialize the DHCP message header */ 00734 result = dhcp_create_msg(netif, &dhcp, DHCP_INFORM); 00735 if (result == ERR_OK) { 00736 dhcp_option(&dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); 00737 dhcp_option_short(&dhcp, DHCP_MAX_MSG_LEN(netif)); 00738 00739 dhcp_option_trailer(&dhcp); 00740 00741 pbuf_realloc(dhcp.p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp.options_out_len); 00742 00743 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_inform: INFORMING\n")); 00744 udp_sendto_if(pcb, dhcp.p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); 00745 dhcp_delete_msg(&dhcp); 00746 } else { 00747 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_inform: could not allocate DHCP request\n")); 00748 } 00749 00750 if (dhcp.pcb != NULL) { 00751 /* otherwise, the existing pcb was used */ 00752 udp_remove(dhcp.pcb); 00753 } 00754 } 00755 00756 /** Handle a possible change in the network configuration. 00757 * 00758 * This enters the REBOOTING state to verify that the currently bound 00759 * address is still valid. 00760 */ 00761 void 00762 dhcp_network_changed(struct netif *netif) 00763 { 00764 struct dhcp *dhcp = netif->dhcp; 00765 if (!dhcp) 00766 return; 00767 switch (dhcp->state) { 00768 case DHCP_REBINDING: 00769 case DHCP_RENEWING: 00770 case DHCP_BOUND: 00771 case DHCP_REBOOTING: 00772 netif_set_down(netif); 00773 dhcp->tries = 0; 00774 dhcp_reboot(netif); 00775 break; 00776 case DHCP_OFF: 00777 /* stay off */ 00778 break; 00779 default: 00780 dhcp->tries = 0; 00781 #if LWIP_DHCP_AUTOIP_COOP 00782 if(dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) { 00783 autoip_stop(netif); 00784 dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF; 00785 } 00786 #endif /* LWIP_DHCP_AUTOIP_COOP */ 00787 dhcp_discover(netif); 00788 break; 00789 } 00790 } 00791 00792 #if DHCP_DOES_ARP_CHECK 00793 /** 00794 * Match an ARP reply with the offered IP address. 00795 * 00796 * @param netif the network interface on which the reply was received 00797 * @param addr The IP address we received a reply from 00798 */ 00799 void dhcp_arp_reply(struct netif *netif, ip_addr_t *addr) 00800 { 00801 LWIP_ERROR("netif != NULL", (netif != NULL), return;); 00802 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_arp_reply()\n")); 00803 /* is a DHCP client doing an ARP check? */ 00804 if ((netif->dhcp != NULL) && (netif->dhcp->state == DHCP_CHECKING)) { 00805 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_arp_reply(): CHECKING, arp reply for 0x%08"X32_F"\n", 00806 ip4_addr_get_u32(addr))); 00807 /* did a host respond with the address we 00808 were offered by the DHCP server? */ 00809 if (ip_addr_cmp(addr, &netif->dhcp->offered_ip_addr)) { 00810 /* we will not accept the offered address */ 00811 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING, 00812 ("dhcp_arp_reply(): arp reply matched with offered address, declining\n")); 00813 dhcp_decline(netif); 00814 } 00815 } 00816 } 00817 00818 /** 00819 * Decline an offered lease. 00820 * 00821 * Tell the DHCP server we do not accept the offered address. 00822 * One reason to decline the lease is when we find out the address 00823 * is already in use by another host (through ARP). 00824 * 00825 * @param netif the netif under DHCP control 00826 */ 00827 static err_t 00828 dhcp_decline(struct netif *netif) 00829 { 00830 struct dhcp *dhcp = netif->dhcp; 00831 err_t result = ERR_OK; 00832 u16_t msecs; 00833 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_decline()\n")); 00834 dhcp_set_state(dhcp, DHCP_BACKING_OFF); 00835 /* create and initialize the DHCP message header */ 00836 result = dhcp_create_msg(netif, dhcp, DHCP_DECLINE); 00837 if (result == ERR_OK) { 00838 dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4); 00839 dhcp_option_long(dhcp, ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr))); 00840 00841 dhcp_option_trailer(dhcp); 00842 /* resize pbuf to reflect true size of options */ 00843 pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); 00844 00845 /* per section 4.4.4, broadcast DECLINE messages */ 00846 udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); 00847 dhcp_delete_msg(dhcp); 00848 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_decline: BACKING OFF\n")); 00849 } else { 00850 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, 00851 ("dhcp_decline: could not allocate DHCP request\n")); 00852 } 00853 dhcp->tries++; 00854 msecs = 10*1000; 00855 dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; 00856 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_decline(): set request timeout %"U16_F" msecs\n", msecs)); 00857 return result; 00858 } 00859 #endif /* DHCP_DOES_ARP_CHECK */ 00860 00861 00862 /** 00863 * Start the DHCP process, discover a DHCP server. 00864 * 00865 * @param netif the netif under DHCP control 00866 */ 00867 static err_t 00868 dhcp_discover(struct netif *netif) 00869 { 00870 struct dhcp *dhcp = netif->dhcp; 00871 err_t result = ERR_OK; 00872 u16_t msecs; 00873 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover()\n")); 00874 ip_addr_set_any(&dhcp->offered_ip_addr); 00875 dhcp_set_state(dhcp, DHCP_SELECTING); 00876 /* create and initialize the DHCP message header */ 00877 result = dhcp_create_msg(netif, dhcp, DHCP_DISCOVER); 00878 if (result == ERR_OK) { 00879 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: making request\n")); 00880 00881 dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); 00882 dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); 00883 00884 dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 4/*num options*/); 00885 dhcp_option_byte(dhcp, DHCP_OPTION_SUBNET_MASK); 00886 dhcp_option_byte(dhcp, DHCP_OPTION_ROUTER); 00887 dhcp_option_byte(dhcp, DHCP_OPTION_BROADCAST); 00888 dhcp_option_byte(dhcp, DHCP_OPTION_DNS_SERVER); 00889 00890 dhcp_option_trailer(dhcp); 00891 00892 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: realloc()ing\n")); 00893 pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); 00894 00895 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, DHCP_SERVER_PORT)\n")); 00896 udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); 00897 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: deleting()ing\n")); 00898 dhcp_delete_msg(dhcp); 00899 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover: SELECTING\n")); 00900 } else { 00901 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_discover: could not allocate DHCP request\n")); 00902 } 00903 dhcp->tries++; 00904 #if LWIP_DHCP_AUTOIP_COOP 00905 if(dhcp->tries >= LWIP_DHCP_AUTOIP_COOP_TRIES && dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_OFF) { 00906 dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_ON; 00907 autoip_start(netif); 00908 } 00909 #endif /* LWIP_DHCP_AUTOIP_COOP */ 00910 msecs = (dhcp->tries < 6 ? 1 << dhcp->tries : 60) * 1000; 00911 dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; 00912 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover(): set request timeout %"U16_F" msecs\n", msecs)); 00913 return result; 00914 } 00915 00916 00917 /** 00918 * Bind the interface to the offered IP address. 00919 * 00920 * @param netif network interface to bind to the offered address 00921 */ 00922 static void 00923 dhcp_bind(struct netif *netif) 00924 { 00925 u32_t timeout; 00926 struct dhcp *dhcp; 00927 ip_addr_t sn_mask, gw_addr; 00928 LWIP_ERROR("dhcp_bind: netif != NULL", (netif != NULL), return;); 00929 dhcp = netif->dhcp; 00930 LWIP_ERROR("dhcp_bind: dhcp != NULL", (dhcp != NULL), return;); 00931 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)); 00932 00933 /* temporary DHCP lease? */ 00934 if (dhcp->offered_t1_renew != 0xffffffffUL) { 00935 /* set renewal period timer */ 00936 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t1 renewal timer %"U32_F" secs\n", dhcp->offered_t1_renew)); 00937 timeout = (dhcp->offered_t1_renew + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS; 00938 if(timeout > 0xffff) { 00939 timeout = 0xffff; 00940 } 00941 dhcp->t1_timeout = (u16_t)timeout; 00942 if (dhcp->t1_timeout == 0) { 00943 dhcp->t1_timeout = 1; 00944 } 00945 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t1_renew*1000)); 00946 } 00947 /* set renewal period timer */ 00948 if (dhcp->offered_t2_rebind != 0xffffffffUL) { 00949 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t2 rebind timer %"U32_F" secs\n", dhcp->offered_t2_rebind)); 00950 timeout = (dhcp->offered_t2_rebind + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS; 00951 if(timeout > 0xffff) { 00952 timeout = 0xffff; 00953 } 00954 dhcp->t2_timeout = (u16_t)timeout; 00955 if (dhcp->t2_timeout == 0) { 00956 dhcp->t2_timeout = 1; 00957 } 00958 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t2_rebind*1000)); 00959 } 00960 00961 if (dhcp->subnet_mask_given) { 00962 /* copy offered network mask */ 00963 ip_addr_copy(sn_mask, dhcp->offered_sn_mask); 00964 } else { 00965 /* subnet mask not given, choose a safe subnet mask given the network class */ 00966 u8_t first_octet = ip4_addr1(&dhcp->offered_ip_addr); 00967 if (first_octet <= 127) { 00968 ip4_addr_set_u32(&sn_mask, PP_HTONL(0xff000000UL)); 00969 } else if (first_octet >= 192) { 00970 ip4_addr_set_u32(&sn_mask, PP_HTONL(0xffffff00UL)); 00971 } else { 00972 ip4_addr_set_u32(&sn_mask, PP_HTONL(0xffff0000UL)); 00973 } 00974 } 00975 00976 ip_addr_copy(gw_addr, dhcp->offered_gw_addr); 00977 /* gateway address not given? */ 00978 if (gw_addr.addr == IPADDR_ANY) { 00979 /* copy network address */ 00980 ip_addr_get_network(&gw_addr, &dhcp->offered_ip_addr, &sn_mask); 00981 /* use first host address on network as gateway */ 00982 ip4_addr_set_u32(&gw_addr, ip4_addr_get_u32(&gw_addr) | PP_HTONL(0x00000001UL)); 00983 } 00984 00985 #if LWIP_DHCP_AUTOIP_COOP 00986 if(dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) { 00987 autoip_stop(netif); 00988 dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF; 00989 } 00990 #endif /* LWIP_DHCP_AUTOIP_COOP */ 00991 00992 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): IP: 0x%08"X32_F"\n", 00993 ip4_addr_get_u32(&dhcp->offered_ip_addr))); 00994 netif_set_ipaddr(netif, &dhcp->offered_ip_addr); 00995 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): SN: 0x%08"X32_F"\n", 00996 ip4_addr_get_u32(&sn_mask))); 00997 netif_set_netmask(netif, &sn_mask); 00998 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): GW: 0x%08"X32_F"\n", 00999 ip4_addr_get_u32(&gw_addr))); 01000 netif_set_gw(netif, &gw_addr); 01001 /* bring the interface up */ 01002 netif_set_up(netif); 01003 /* netif is now bound to DHCP leased address */ 01004 dhcp_set_state(dhcp, DHCP_BOUND); 01005 } 01006 01007 /** 01008 * Renew an existing DHCP lease at the involved DHCP server. 01009 * 01010 * @param netif network interface which must renew its lease 01011 */ 01012 err_t 01013 dhcp_renew(struct netif *netif) 01014 { 01015 struct dhcp *dhcp = netif->dhcp; 01016 err_t result; 01017 u16_t msecs; 01018 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_renew()\n")); 01019 dhcp_set_state(dhcp, DHCP_RENEWING); 01020 01021 /* create and initialize the DHCP message header */ 01022 result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST); 01023 if (result == ERR_OK) { 01024 dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); 01025 dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); 01026 01027 #if LWIP_NETIF_HOSTNAME 01028 if (netif->hostname != NULL) { 01029 const char *p = (const char*)netif->hostname; 01030 u8_t namelen = (u8_t)strlen(p); 01031 if (namelen > 0) { 01032 LWIP_ASSERT("DHCP: hostname is too long!", namelen < 255); 01033 dhcp_option(dhcp, DHCP_OPTION_HOSTNAME, namelen); 01034 while (*p) { 01035 dhcp_option_byte(dhcp, *p++); 01036 } 01037 } 01038 } 01039 #endif /* LWIP_NETIF_HOSTNAME */ 01040 01041 #if 0 01042 dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4); 01043 dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr)); 01044 #endif 01045 01046 #if 0 01047 dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4); 01048 dhcp_option_long(dhcp, ntohl(dhcp->server_ip_addr.addr)); 01049 #endif 01050 /* append DHCP message trailer */ 01051 dhcp_option_trailer(dhcp); 01052 01053 pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); 01054 01055 udp_sendto_if(dhcp->pcb, dhcp->p_out, &dhcp->server_ip_addr, DHCP_SERVER_PORT, netif); 01056 dhcp_delete_msg(dhcp); 01057 01058 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_renew: RENEWING\n")); 01059 } else { 01060 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_renew: could not allocate DHCP request\n")); 01061 } 01062 dhcp->tries++; 01063 /* back-off on retries, but to a maximum of 20 seconds */ 01064 msecs = dhcp->tries < 10 ? dhcp->tries * 2000 : 20 * 1000; 01065 dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; 01066 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_renew(): set request timeout %"U16_F" msecs\n", msecs)); 01067 return result; 01068 } 01069 01070 /** 01071 * Rebind with a DHCP server for an existing DHCP lease. 01072 * 01073 * @param netif network interface which must rebind with a DHCP server 01074 */ 01075 static err_t 01076 dhcp_rebind(struct netif *netif) 01077 { 01078 struct dhcp *dhcp = netif->dhcp; 01079 err_t result; 01080 u16_t msecs; 01081 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind()\n")); 01082 dhcp_set_state(dhcp, DHCP_REBINDING); 01083 01084 /* create and initialize the DHCP message header */ 01085 result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST); 01086 if (result == ERR_OK) { 01087 dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); 01088 dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); 01089 01090 #if LWIP_NETIF_HOSTNAME 01091 if (netif->hostname != NULL) { 01092 const char *p = (const char*)netif->hostname; 01093 u8_t namelen = (u8_t)strlen(p); 01094 if (namelen > 0) { 01095 LWIP_ASSERT("DHCP: hostname is too long!", namelen < 255); 01096 dhcp_option(dhcp, DHCP_OPTION_HOSTNAME, namelen); 01097 while (*p) { 01098 dhcp_option_byte(dhcp, *p++); 01099 } 01100 } 01101 } 01102 #endif /* LWIP_NETIF_HOSTNAME */ 01103 01104 #if 0 01105 dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4); 01106 dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr)); 01107 01108 dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4); 01109 dhcp_option_long(dhcp, ntohl(dhcp->server_ip_addr.addr)); 01110 #endif 01111 01112 dhcp_option_trailer(dhcp); 01113 01114 pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); 01115 01116 /* broadcast to server */ 01117 udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); 01118 dhcp_delete_msg(dhcp); 01119 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind: REBINDING\n")); 01120 } else { 01121 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_rebind: could not allocate DHCP request\n")); 01122 } 01123 dhcp->tries++; 01124 msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000; 01125 dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; 01126 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind(): set request timeout %"U16_F" msecs\n", msecs)); 01127 return result; 01128 } 01129 01130 /** 01131 * Enter REBOOTING state to verify an existing lease 01132 * 01133 * @param netif network interface which must reboot 01134 */ 01135 static err_t 01136 dhcp_reboot(struct netif *netif) 01137 { 01138 struct dhcp *dhcp = netif->dhcp; 01139 err_t result; 01140 u16_t msecs; 01141 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot()\n")); 01142 dhcp_set_state(dhcp, DHCP_REBOOTING); 01143 01144 /* create and initialize the DHCP message header */ 01145 result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST); 01146 if (result == ERR_OK) { 01147 dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); 01148 dhcp_option_short(dhcp, 576); 01149 01150 dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4); 01151 dhcp_option_long(dhcp, ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr))); 01152 01153 dhcp_option_trailer(dhcp); 01154 01155 pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); 01156 01157 /* broadcast to server */ 01158 udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); 01159 dhcp_delete_msg(dhcp); 01160 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot: REBOOTING\n")); 01161 } else { 01162 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_reboot: could not allocate DHCP request\n")); 01163 } 01164 dhcp->tries++; 01165 msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000; 01166 dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; 01167 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot(): set request timeout %"U16_F" msecs\n", msecs)); 01168 return result; 01169 } 01170 01171 01172 /** 01173 * Release a DHCP lease. 01174 * 01175 * @param netif network interface which must release its lease 01176 */ 01177 err_t 01178 dhcp_release(struct netif *netif) 01179 { 01180 struct dhcp *dhcp = netif->dhcp; 01181 err_t result; 01182 u16_t msecs; 01183 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_release()\n")); 01184 01185 /* idle DHCP client */ 01186 dhcp_set_state(dhcp, DHCP_OFF); 01187 /* clean old DHCP offer */ 01188 ip_addr_set_zero(&dhcp->server_ip_addr); 01189 ip_addr_set_zero(&dhcp->offered_ip_addr); 01190 ip_addr_set_zero(&dhcp->offered_sn_mask); 01191 ip_addr_set_zero(&dhcp->offered_gw_addr); 01192 #if LWIP_DHCP_BOOTP_FILE 01193 ip_addr_set_zero(&dhcp->offered_si_addr); 01194 #endif /* LWIP_DHCP_BOOTP_FILE */ 01195 dhcp->offered_t0_lease = dhcp->offered_t1_renew = dhcp->offered_t2_rebind = 0; 01196 01197 /* create and initialize the DHCP message header */ 01198 result = dhcp_create_msg(netif, dhcp, DHCP_RELEASE); 01199 if (result == ERR_OK) { 01200 dhcp_option_trailer(dhcp); 01201 01202 pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); 01203 01204 udp_sendto_if(dhcp->pcb, dhcp->p_out, &dhcp->server_ip_addr, DHCP_SERVER_PORT, netif); 01205 dhcp_delete_msg(dhcp); 01206 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_release: RELEASED, DHCP_OFF\n")); 01207 } else { 01208 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_release: could not allocate DHCP request\n")); 01209 } 01210 dhcp->tries++; 01211 msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000; 01212 dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; 01213 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_release(): set request timeout %"U16_F" msecs\n", msecs)); 01214 /* bring the interface down */ 01215 netif_set_down(netif); 01216 /* remove IP address from interface */ 01217 netif_set_ipaddr(netif, IP_ADDR_ANY); 01218 netif_set_gw(netif, IP_ADDR_ANY); 01219 netif_set_netmask(netif, IP_ADDR_ANY); 01220 01221 return result; 01222 } 01223 01224 /** 01225 * Remove the DHCP client from the interface. 01226 * 01227 * @param netif The network interface to stop DHCP on 01228 */ 01229 void 01230 dhcp_stop(struct netif *netif) 01231 { 01232 struct dhcp *dhcp; 01233 LWIP_ERROR("dhcp_stop: netif != NULL", (netif != NULL), return;); 01234 dhcp = netif->dhcp; 01235 /* Remove the flag that says this netif is handled by DHCP. */ 01236 netif->flags &= ~NETIF_FLAG_DHCP; 01237 01238 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_stop()\n")); 01239 /* netif is DHCP configured? */ 01240 if (dhcp != NULL) { 01241 #if LWIP_DHCP_AUTOIP_COOP 01242 if(dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) { 01243 autoip_stop(netif); 01244 dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF; 01245 } 01246 #endif /* LWIP_DHCP_AUTOIP_COOP */ 01247 01248 if (dhcp->pcb != NULL) { 01249 udp_remove(dhcp->pcb); 01250 dhcp->pcb = NULL; 01251 } 01252 LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL); 01253 dhcp_set_state(dhcp, DHCP_OFF); 01254 } 01255 } 01256 01257 /* 01258 * Set the DHCP state of a DHCP client. 01259 * 01260 * If the state changed, reset the number of tries. 01261 */ 01262 static void 01263 dhcp_set_state(struct dhcp *dhcp, u8_t new_state) 01264 { 01265 if (new_state != dhcp->state) { 01266 dhcp->state = new_state; 01267 dhcp->tries = 0; 01268 dhcp->request_timeout = 0; 01269 } 01270 } 01271 01272 /* 01273 * Concatenate an option type and length field to the outgoing 01274 * DHCP message. 01275 * 01276 */ 01277 static void 01278 dhcp_option(struct dhcp *dhcp, u8_t option_type, u8_t option_len) 01279 { 01280 LWIP_ASSERT("dhcp_option: dhcp->options_out_len + 2 + option_len <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 2U + option_len <= DHCP_OPTIONS_LEN); 01281 dhcp->msg_out->options[dhcp->options_out_len++] = option_type; 01282 dhcp->msg_out->options[dhcp->options_out_len++] = option_len; 01283 } 01284 /* 01285 * Concatenate a single byte to the outgoing DHCP message. 01286 * 01287 */ 01288 static void 01289 dhcp_option_byte(struct dhcp *dhcp, u8_t value) 01290 { 01291 LWIP_ASSERT("dhcp_option_byte: dhcp->options_out_len < DHCP_OPTIONS_LEN", dhcp->options_out_len < DHCP_OPTIONS_LEN); 01292 dhcp->msg_out->options[dhcp->options_out_len++] = value; 01293 } 01294 01295 static void 01296 dhcp_option_short(struct dhcp *dhcp, u16_t value) 01297 { 01298 LWIP_ASSERT("dhcp_option_short: dhcp->options_out_len + 2 <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 2U <= DHCP_OPTIONS_LEN); 01299 dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0xff00U) >> 8); 01300 dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t) (value & 0x00ffU); 01301 } 01302 01303 static void 01304 dhcp_option_long(struct dhcp *dhcp, u32_t value) 01305 { 01306 LWIP_ASSERT("dhcp_option_long: dhcp->options_out_len + 4 <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 4U <= DHCP_OPTIONS_LEN); 01307 dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0xff000000UL) >> 24); 01308 dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x00ff0000UL) >> 16); 01309 dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x0000ff00UL) >> 8); 01310 dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x000000ffUL)); 01311 } 01312 01313 /** 01314 * Extract the DHCP message and the DHCP options. 01315 * 01316 * Extract the DHCP message and the DHCP options, each into a contiguous 01317 * piece of memory. As a DHCP message is variable sized by its options, 01318 * and also allows overriding some fields for options, the easy approach 01319 * is to first unfold the options into a conitguous piece of memory, and 01320 * use that further on. 01321 * 01322 */ 01323 static err_t 01324 dhcp_parse_reply(struct dhcp *dhcp, struct pbuf *p) 01325 { 01326 u8_t *options; 01327 u16_t offset; 01328 u16_t offset_max; 01329 u16_t options_idx; 01330 u16_t options_idx_max; 01331 struct pbuf *q; 01332 int parse_file_as_options = 0; 01333 int parse_sname_as_options = 0; 01334 01335 /* clear received options */ 01336 dhcp_clear_all_options(dhcp); 01337 /* check that beginning of dhcp_msg (up to and including chaddr) is in first pbuf */ 01338 if (p->len < DHCP_SNAME_OFS) { 01339 return ERR_BUF; 01340 } 01341 dhcp->msg_in = (struct dhcp_msg *)p->payload; 01342 #if LWIP_DHCP_BOOTP_FILE 01343 /* clear boot file name */ 01344 dhcp->boot_file_name[0] = 0; 01345 #endif /* LWIP_DHCP_BOOTP_FILE */ 01346 01347 /* parse options */ 01348 01349 /* start with options field */ 01350 options_idx = DHCP_OPTIONS_OFS; 01351 /* parse options to the end of the received packet */ 01352 options_idx_max = p->tot_len; 01353 again: 01354 q = p; 01355 while((q != NULL) && (options_idx >= q->len)) { 01356 options_idx -= q->len; 01357 options_idx_max -= q->len; 01358 q = q->next; 01359 } 01360 if (q == NULL) { 01361 return ERR_BUF; 01362 } 01363 offset = options_idx; 01364 offset_max = options_idx_max; 01365 options = (u8_t*)q->payload; 01366 /* at least 1 byte to read and no end marker, then at least 3 bytes to read? */ 01367 while((q != NULL) && (options[offset] != DHCP_OPTION_END) && (offset < offset_max)) { 01368 u8_t op = options[offset]; 01369 u8_t len; 01370 u8_t decode_len = 0; 01371 int decode_idx = -1; 01372 u16_t val_offset = offset + 2; 01373 /* len byte might be in the next pbuf */ 01374 if (offset + 1 < q->len) { 01375 len = options[offset + 1]; 01376 } else { 01377 len = (q->next != NULL ? ((u8_t*)q->next->payload)[0] : 0); 01378 } 01379 /* LWIP_DEBUGF(DHCP_DEBUG, ("msg_offset=%"U16_F", q->len=%"U16_F, msg_offset, q->len)); */ 01380 decode_len = len; 01381 switch(op) { 01382 /* case(DHCP_OPTION_END): handled above */ 01383 case(DHCP_OPTION_PAD): 01384 /* special option: no len encoded */ 01385 decode_len = len = 0; 01386 /* will be increased below */ 01387 offset--; 01388 break; 01389 case(DHCP_OPTION_SUBNET_MASK): 01390 LWIP_ASSERT("len == 4", len == 4); 01391 decode_idx = DHCP_OPTION_IDX_SUBNET_MASK; 01392 break; 01393 case(DHCP_OPTION_ROUTER): 01394 decode_len = 4; /* only copy the first given router */ 01395 LWIP_ASSERT("len >= decode_len", len >= decode_len); 01396 decode_idx = DHCP_OPTION_IDX_ROUTER; 01397 break; 01398 case(DHCP_OPTION_DNS_SERVER): 01399 /* special case: there might be more than one server */ 01400 LWIP_ASSERT("len % 4 == 0", len % 4 == 0); 01401 /* limit number of DNS servers */ 01402 decode_len = LWIP_MIN(len, 4 * DNS_MAX_SERVERS); 01403 LWIP_ASSERT("len >= decode_len", len >= decode_len); 01404 decode_idx = DHCP_OPTION_IDX_DNS_SERVER; 01405 break; 01406 case(DHCP_OPTION_LEASE_TIME): 01407 LWIP_ASSERT("len == 4", len == 4); 01408 decode_idx = DHCP_OPTION_IDX_LEASE_TIME; 01409 break; 01410 case(DHCP_OPTION_OVERLOAD): 01411 LWIP_ASSERT("len == 1", len == 1); 01412 decode_idx = DHCP_OPTION_IDX_OVERLOAD; 01413 break; 01414 case(DHCP_OPTION_MESSAGE_TYPE): 01415 LWIP_ASSERT("len == 1", len == 1); 01416 decode_idx = DHCP_OPTION_IDX_MSG_TYPE; 01417 break; 01418 case(DHCP_OPTION_SERVER_ID): 01419 LWIP_ASSERT("len == 4", len == 4); 01420 decode_idx = DHCP_OPTION_IDX_SERVER_ID; 01421 break; 01422 case(DHCP_OPTION_T1): 01423 LWIP_ASSERT("len == 4", len == 4); 01424 decode_idx = DHCP_OPTION_IDX_T1; 01425 break; 01426 case(DHCP_OPTION_T2): 01427 LWIP_ASSERT("len == 4", len == 4); 01428 decode_idx = DHCP_OPTION_IDX_T2; 01429 break; 01430 default: 01431 decode_len = 0; 01432 LWIP_DEBUGF(DHCP_DEBUG, ("skipping option %"U16_F" in options\n", op)); 01433 break; 01434 } 01435 offset += len + 2; 01436 if (decode_len > 0) { 01437 u32_t value = 0; 01438 u16_t copy_len; 01439 decode_next: 01440 LWIP_ASSERT("check decode_idx", decode_idx >= 0 && decode_idx < DHCP_OPTION_IDX_MAX); 01441 LWIP_ASSERT("option already decoded", !dhcp_option_given(dhcp, decode_idx)); 01442 copy_len = LWIP_MIN(decode_len, 4); 01443 pbuf_copy_partial(q, &value, copy_len, val_offset); 01444 if (decode_len > 4) { 01445 /* decode more than one u32_t */ 01446 LWIP_ASSERT("decode_len % 4 == 0", decode_len % 4 == 0); 01447 dhcp_got_option(dhcp, decode_idx); 01448 dhcp_set_option_value(dhcp, decode_idx, htonl(value)); 01449 decode_len -= 4; 01450 val_offset += 4; 01451 decode_idx++; 01452 goto decode_next; 01453 } else if (decode_len == 4) { 01454 value = ntohl(value); 01455 } else { 01456 LWIP_ASSERT("invalid decode_len", decode_len == 1); 01457 value = ((u8_t*)&value)[0]; 01458 } 01459 dhcp_got_option(dhcp, decode_idx); 01460 dhcp_set_option_value(dhcp, decode_idx, value); 01461 } 01462 if (offset >= q->len) { 01463 offset -= q->len; 01464 offset_max -= q->len; 01465 q = q->next; 01466 options = (u8_t*)q->payload; 01467 } 01468 } 01469 /* is this an overloaded message? */ 01470 if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_OVERLOAD)) { 01471 u32_t overload = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_OVERLOAD); 01472 dhcp_clear_option(dhcp, DHCP_OPTION_IDX_OVERLOAD); 01473 if (overload == DHCP_OVERLOAD_FILE) { 01474 parse_file_as_options = 1; 01475 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded file field\n")); 01476 } else if (overload == DHCP_OVERLOAD_SNAME) { 01477 parse_sname_as_options = 1; 01478 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded sname field\n")); 01479 } else if (overload == DHCP_OVERLOAD_SNAME_FILE) { 01480 parse_sname_as_options = 1; 01481 parse_file_as_options = 1; 01482 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded sname and file field\n")); 01483 } else { 01484 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("invalid overload option: %d\n", (int)overload)); 01485 } 01486 #if LWIP_DHCP_BOOTP_FILE 01487 if (!parse_file_as_options) { 01488 /* only do this for ACK messages */ 01489 if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_MSG_TYPE) && 01490 (dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_MSG_TYPE) == DHCP_ACK)) 01491 /* copy bootp file name, don't care for sname (server hostname) */ 01492 pbuf_copy_partial(p, dhcp->boot_file_name, DHCP_FILE_LEN-1, DHCP_FILE_OFS); 01493 /* make sure the string is really NULL-terminated */ 01494 dhcp->boot_file_name[DHCP_FILE_LEN-1] = 0; 01495 } 01496 #endif /* LWIP_DHCP_BOOTP_FILE */ 01497 } 01498 if (parse_file_as_options) { 01499 /* if both are overloaded, parse file first and then sname (RFC 2131 ch. 4.1) */ 01500 parse_file_as_options = 0; 01501 options_idx = DHCP_FILE_OFS; 01502 options_idx_max = DHCP_FILE_OFS + DHCP_FILE_LEN; 01503 goto again; 01504 } else if (parse_sname_as_options) { 01505 parse_sname_as_options = 0; 01506 options_idx = DHCP_SNAME_OFS; 01507 options_idx_max = DHCP_SNAME_OFS + DHCP_SNAME_LEN; 01508 goto again; 01509 } 01510 return ERR_OK; 01511 } 01512 01513 /** 01514 * If an incoming DHCP message is in response to us, then trigger the state machine 01515 */ 01516 static void 01517 dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port) 01518 { 01519 struct netif *netif = (struct netif *)arg; 01520 struct dhcp *dhcp = netif->dhcp; 01521 struct dhcp_msg *reply_msg = (struct dhcp_msg *)p->payload; 01522 u8_t msg_type; 01523 u8_t i; 01524 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, 01525 ip4_addr1_16(addr), ip4_addr2_16(addr), ip4_addr3_16(addr), ip4_addr4_16(addr), port)); 01526 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("pbuf->len = %"U16_F"\n", p->len)); 01527 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("pbuf->tot_len = %"U16_F"\n", p->tot_len)); 01528 /* prevent warnings about unused arguments */ 01529 LWIP_UNUSED_ARG(pcb); 01530 LWIP_UNUSED_ARG(addr); 01531 LWIP_UNUSED_ARG(port); 01532 01533 LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL); 01534 01535 if (p->len < DHCP_MIN_REPLY_LEN) { 01536 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("DHCP reply message or pbuf too short\n")); 01537 goto free_pbuf_and_return; 01538 } 01539 01540 if (reply_msg->op != DHCP_BOOTREPLY) { 01541 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)); 01542 goto free_pbuf_and_return; 01543 } 01544 /* iterate through hardware address and match against DHCP message */ 01545 for (i = 0; i < netif->hwaddr_len; i++) { 01546 if (netif->hwaddr[i] != reply_msg->chaddr[i]) { 01547 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, 01548 ("netif->hwaddr[%"U16_F"]==%02"X16_F" != reply_msg->chaddr[%"U16_F"]==%02"X16_F"\n", 01549 (u16_t)i, (u16_t)netif->hwaddr[i], (u16_t)i, (u16_t)reply_msg->chaddr[i])); 01550 goto free_pbuf_and_return; 01551 } 01552 } 01553 /* match transaction ID against what we expected */ 01554 if (ntohl(reply_msg->xid) != dhcp->xid) { 01555 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, 01556 ("transaction id mismatch reply_msg->xid(%"X32_F")!=dhcp->xid(%"X32_F")\n",ntohl(reply_msg->xid),dhcp->xid)); 01557 goto free_pbuf_and_return; 01558 } 01559 /* option fields could be unfold? */ 01560 if (dhcp_parse_reply(dhcp, p) != ERR_OK) { 01561 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, 01562 ("problem unfolding DHCP message - too short on memory?\n")); 01563 goto free_pbuf_and_return; 01564 } 01565 01566 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("searching DHCP_OPTION_MESSAGE_TYPE\n")); 01567 /* obtain pointer to DHCP message type */ 01568 if (!dhcp_option_given(dhcp, DHCP_OPTION_IDX_MSG_TYPE)) { 01569 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("DHCP_OPTION_MESSAGE_TYPE option not found\n")); 01570 goto free_pbuf_and_return; 01571 } 01572 01573 /* read DHCP message type */ 01574 msg_type = (u8_t)dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_MSG_TYPE); 01575 /* message type is DHCP ACK? */ 01576 if (msg_type == DHCP_ACK) { 01577 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_ACK received\n")); 01578 /* in requesting state? */ 01579 if (dhcp->state == DHCP_REQUESTING) { 01580 dhcp_handle_ack(netif); 01581 #if DHCP_DOES_ARP_CHECK 01582 /* check if the acknowledged lease address is already in use */ 01583 dhcp_check(netif); 01584 #else 01585 /* bind interface to the acknowledged lease address */ 01586 dhcp_bind(netif); 01587 #endif 01588 } 01589 /* already bound to the given lease address? */ 01590 else if ((dhcp->state == DHCP_REBOOTING) || (dhcp->state == DHCP_REBINDING) || (dhcp->state == DHCP_RENEWING)) { 01591 dhcp_bind(netif); 01592 } 01593 } 01594 /* received a DHCP_NAK in appropriate state? */ 01595 else if ((msg_type == DHCP_NAK) && 01596 ((dhcp->state == DHCP_REBOOTING) || (dhcp->state == DHCP_REQUESTING) || 01597 (dhcp->state == DHCP_REBINDING) || (dhcp->state == DHCP_RENEWING ))) { 01598 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_NAK received\n")); 01599 dhcp_handle_nak(netif); 01600 } 01601 /* received a DHCP_OFFER in DHCP_SELECTING state? */ 01602 else if ((msg_type == DHCP_OFFER) && (dhcp->state == DHCP_SELECTING)) { 01603 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_OFFER received in DHCP_SELECTING state\n")); 01604 dhcp->request_timeout = 0; 01605 /* remember offered lease */ 01606 dhcp_handle_offer(netif); 01607 } 01608 free_pbuf_and_return: 01609 dhcp->msg_in = NULL; 01610 pbuf_free(p); 01611 } 01612 01613 /** 01614 * Create a DHCP request, fill in common headers 01615 * 01616 * @param netif the netif under DHCP control 01617 * @param dhcp dhcp control struct 01618 * @param message_type message type of the request 01619 */ 01620 static err_t 01621 dhcp_create_msg(struct netif *netif, struct dhcp *dhcp, u8_t message_type) 01622 { 01623 u16_t i; 01624 #ifndef DHCP_GLOBAL_XID 01625 /** default global transaction identifier starting value (easy to match 01626 * with a packet analyser). We simply increment for each new request. 01627 * Predefine DHCP_GLOBAL_XID to a better value or a function call to generate one 01628 * at runtime, any supporting function prototypes can be defined in DHCP_GLOBAL_XID_HEADER */ 01629 static u32_t xid = 0xABCD0000; 01630 #else 01631 static u32_t xid; 01632 static u8_t xid_initialised = 0; 01633 if (!xid_initialised) { 01634 xid = DHCP_GLOBAL_XID; 01635 xid_initialised = !xid_initialised; 01636 } 01637 #endif 01638 LWIP_ERROR("dhcp_create_msg: netif != NULL", (netif != NULL), return ERR_ARG;); 01639 LWIP_ERROR("dhcp_create_msg: dhcp != NULL", (dhcp != NULL), return ERR_VAL;); 01640 LWIP_ASSERT("dhcp_create_msg: dhcp->p_out == NULL", dhcp->p_out == NULL); 01641 LWIP_ASSERT("dhcp_create_msg: dhcp->msg_out == NULL", dhcp->msg_out == NULL); 01642 dhcp->p_out = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcp_msg), PBUF_RAM); 01643 if (dhcp->p_out == NULL) { 01644 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, 01645 ("dhcp_create_msg(): could not allocate pbuf\n")); 01646 return ERR_MEM; 01647 } 01648 LWIP_ASSERT("dhcp_create_msg: check that first pbuf can hold struct dhcp_msg", 01649 (dhcp->p_out->len >= sizeof(struct dhcp_msg))); 01650 01651 /* reuse transaction identifier in retransmissions */ 01652 if (dhcp->tries == 0) { 01653 xid++; 01654 } 01655 dhcp->xid = xid; 01656 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, 01657 ("transaction id xid(%"X32_F")\n", xid)); 01658 01659 dhcp->msg_out = (struct dhcp_msg *)dhcp->p_out->payload; 01660 01661 dhcp->msg_out->op = DHCP_BOOTREQUEST; 01662 /* TODO: make link layer independent */ 01663 dhcp->msg_out->htype = DHCP_HTYPE_ETH; 01664 dhcp->msg_out->hlen = netif->hwaddr_len; 01665 dhcp->msg_out->hops = 0; 01666 dhcp->msg_out->xid = htonl(dhcp->xid); 01667 dhcp->msg_out->secs = 0; 01668 /* we don't need the broadcast flag since we can receive unicast traffic 01669 before being fully configured! */ 01670 dhcp->msg_out->flags = 0; 01671 ip_addr_set_zero(&dhcp->msg_out->ciaddr); 01672 /* set ciaddr to netif->ip_addr based on message_type and state */ 01673 if ((message_type == DHCP_INFORM) || (message_type == DHCP_DECLINE) || 01674 ((message_type == DHCP_REQUEST) && /* DHCP_BOUND not used for sending! */ 01675 ((dhcp->state==DHCP_RENEWING) || dhcp->state==DHCP_REBINDING))) { 01676 ip_addr_copy(dhcp->msg_out->ciaddr, netif->ip_addr); 01677 } 01678 ip_addr_set_zero(&dhcp->msg_out->yiaddr); 01679 ip_addr_set_zero(&dhcp->msg_out->siaddr); 01680 ip_addr_set_zero(&dhcp->msg_out->giaddr); 01681 for (i = 0; i < netif->hwaddr_len; i++) { 01682 /* copy netif hardware address */ 01683 dhcp->msg_out->chaddr[i] = netif->hwaddr[i]; 01684 } 01685 for ( ; i < DHCP_CHADDR_LEN; i++) { 01686 /* ... pad rest with zeroes */ 01687 dhcp->msg_out->chaddr[i] = 0; 01688 } 01689 for (i = 0; i < DHCP_SNAME_LEN; i++) { 01690 dhcp->msg_out->sname[i] = 0; 01691 } 01692 for (i = 0; i < DHCP_FILE_LEN; i++) { 01693 dhcp->msg_out->file[i] = 0; 01694 } 01695 dhcp->msg_out->cookie = PP_HTONL(DHCP_MAGIC_COOKIE); 01696 dhcp->options_out_len = 0; 01697 /* fill options field with an incrementing array (for debugging purposes) */ 01698 for (i = 0; i < DHCP_OPTIONS_LEN; i++) { 01699 dhcp->msg_out->options[i] = (u8_t)i; /* for debugging only, no matter if truncated */ 01700 } 01701 /* Add option MESSAGE_TYPE */ 01702 dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN); 01703 dhcp_option_byte(dhcp, message_type); 01704 return ERR_OK; 01705 } 01706 01707 /** 01708 * Free previously allocated memory used to send a DHCP request. 01709 * 01710 * @param dhcp the dhcp struct to free the request from 01711 */ 01712 static void 01713 dhcp_delete_msg(struct dhcp *dhcp) 01714 { 01715 LWIP_ERROR("dhcp_delete_msg: dhcp != NULL", (dhcp != NULL), return;); 01716 LWIP_ASSERT("dhcp_delete_msg: dhcp->p_out != NULL", dhcp->p_out != NULL); 01717 LWIP_ASSERT("dhcp_delete_msg: dhcp->msg_out != NULL", dhcp->msg_out != NULL); 01718 if (dhcp->p_out != NULL) { 01719 pbuf_free(dhcp->p_out); 01720 } 01721 dhcp->p_out = NULL; 01722 dhcp->msg_out = NULL; 01723 } 01724 01725 /** 01726 * Add a DHCP message trailer 01727 * 01728 * Adds the END option to the DHCP message, and if 01729 * necessary, up to three padding bytes. 01730 * 01731 * @param dhcp DHCP state structure 01732 */ 01733 static void 01734 dhcp_option_trailer(struct dhcp *dhcp) 01735 { 01736 LWIP_ERROR("dhcp_option_trailer: dhcp != NULL", (dhcp != NULL), return;); 01737 LWIP_ASSERT("dhcp_option_trailer: dhcp->msg_out != NULL\n", dhcp->msg_out != NULL); 01738 LWIP_ASSERT("dhcp_option_trailer: dhcp->options_out_len < DHCP_OPTIONS_LEN\n", dhcp->options_out_len < DHCP_OPTIONS_LEN); 01739 dhcp->msg_out->options[dhcp->options_out_len++] = DHCP_OPTION_END; 01740 /* packet is too small, or not 4 byte aligned? */ 01741 while ((dhcp->options_out_len < DHCP_MIN_OPTIONS_LEN) || (dhcp->options_out_len & 3)) { 01742 /* 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)); */ 01743 LWIP_ASSERT("dhcp_option_trailer: dhcp->options_out_len < DHCP_OPTIONS_LEN\n", dhcp->options_out_len < DHCP_OPTIONS_LEN); 01744 /* add a fill/padding byte */ 01745 dhcp->msg_out->options[dhcp->options_out_len++] = 0; 01746 } 01747 } 01748 01749 #endif /* LWIP_DHCP */
Generated on Tue Jul 12 2022 17:34:40 by
