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