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