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