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