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