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